Java 在所有web应用程序中管理要访问的会话属性

Java 在所有web应用程序中管理要访问的会话属性,java,jsf,tomcat,web-applications,jsf-2,Java,Jsf,Tomcat,Web Applications,Jsf 2,我有一些会话属性,所有应用程序(DAO、业务对象、bean等)都必须可以访问这些属性 我无法创建具有静态属性的类,因为静态属性共享给不同的会话 例如:用户在应用程序中登录,我需要保存登录时间,我需要将此值存储在会话属性中,因为在我的应用程序的某些点(如BO(业务对象))中,我需要知道用户何时登录应用程序 我无法在我的应用程序的某些地方访问HttpRequest,我需要一些其他解决方案 编写一个POJO,其中包含您需要的所有“请求范围”属性,例如“登录时间” 写一篇: public PojoFil

我有一些会话属性,所有应用程序(DAO、业务对象、bean等)都必须可以访问这些属性

我无法创建具有静态属性的类,因为静态属性共享给不同的会话

例如:用户在应用程序中登录,我需要保存登录时间,我需要将此值存储在会话属性中,因为在我的应用程序的某些点(如BO(业务对象))中,我需要知道用户何时登录应用程序

我无法在我的应用程序的某些地方访问HttpRequest,我需要一些其他解决方案

  • 编写一个POJO,其中包含您需要的所有“请求范围”属性,例如“登录时间”
  • 写一篇:

    public PojoFilter实现javax.servlet.Filter{
    private static final ThreadLocal POJO=new ThreadLocal();
    公共无效doFilter(ServletRequest请求、ServletResponse响应、FilterChain FilterChain){
    试一试{
    Pojo Pojo=createPojoFrom(请求);
    POJO.set(POJO);
    filterChain.doFilter(请求、响应);
    }最后{
    POJO.remove();
    }
    }
    公共静态currentPojo(){
    返回POJO.get();
    }
    ...
    }
    
  • 在需要这些值的地方调用PojoFilter.currentPojo()

  • 显然,这可以设计得更好,这样过滤器就不会泄漏到代码的其余部分,但这应该给你一个想法。

    你已经在JSF中标记了它,所以我将给你一个JSF响应和/或泛型

    a) 创建一个
    @SessionScoped
    -ManagedBean并对其应用您的值,然后
    @ManagedProperty
    将其插入您想要访问它的位置(如果需要,创建一个外观)

    b) 只需创建一个“数据模型”对象,将您的信息存储在其中,并将其设置到会话中。例如

    FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("userContext", context);
    
    <代码>由于用户ID是唯一的,我们可以利用这个事实来以更简单的方式实现您的问题(我的解决方案考虑到所有传入的请求都通过通用servlet /过滤器,我在这里使用过滤器): a) 创建一个实用程序类,如下所示: 公共类幸福{ 私有静态映射userLoginTimeStampMap=newhashmap(); 公共静态void addLoginItemStamp(字符串用户ID){ 已同步(apputity.class){ 日期=新日期(); userLoginTimeStampMap.put(userId,date); } } 公共静态日期getUserLoginTimeStamp(字符串用户ID){ 已同步(apputity.class){ 返回userLoginTimeStampMap.get(userId); } } } b) 在过滤器的doFilter方法中,编写如下代码: 公共无效doFilter(ServletRequest请求、ServletResponse响应、FilterChain FilterChain){ 试一试{ 字符串userId=user.getUserId(); apputity.addLoginTimeStamp(userId); }最后{ //做你想做的事 } } c) 现在,在服务或dao之类的任何类中,您都可以轻松获得用户登录时间戳,如下所示: Date-Date=apputility.getUserLoginTimeStamp(userId); 我希望这个解决办法是可行的。
    因此,我设想我可以创建一个ThreadLocal映射,在这里我可以返回一个带有特定名称和特定值的ThreadLocal。每个会话对这张地图都有不同的价值,对吗?我不这么认为。ThreadLocal的一个优点是,每个控制线程都会获得您创建的Pojo的一个单独实例。因此,如果您的应用程序在N个线程上处理N个请求,那么在每个请求期间将存在N个不同的POJO。如果您愿意,您的Pojo可以是一个地图,但这是一个非常松散的抽象概念我无法理解您的想法,您能给我提供更多详细信息吗?第二个解决方案非常好而且优雅,但问题是当我尝试访问FacesContext.getCurrentInstance()时这将返回NULL。那么您确定您实际使用的是JSF吗?您的问题看起来像是应用程序存在一个更基本的设计问题。业务对象应该向应用程序中的其他组件提供服务,而不是反过来。业务对象应该位于提供必要信息的位置,这样组件就可以按需调用业务方法(而不是将一些信息存储在某个位置,然后让业务对象提取数据)。总之,您可以尝试使用
    @ApplicationScoped
    bean,该bean有一个您感兴趣的数据映射,该映射是@kolossus提供的,但他希望的会话范围不是@ApplicationScoped
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("userContext", context);
    
    Since user id is unique, we can utilize this fact to implement your problem in simpler way as follows(My solution consider that all incoming request goes through common servlet/filter, I am using filter here):
    
    a) Create a utility class as:
    
    public class AppUtlity {
        private static Map<String, Date> userLoginTimeStampMap = new HashMap<String, Date>();
    
        public static void addLoginTimeStamp(String userId) {
            synchronized(AppUtlity.class) {
                Date date = new Date();
                userLoginTimeStampMap.put(userId, date);
            }
        }
    
        public static Date getUserLoginTimeStamp(String userId) {
            synchronized(AppUtlity.class) {
                return userLoginTimeStampMap.get(userId);
            }
        }
    }
    
    b) In doFilter method of your filter write code as below:
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
             try {
                 String userId = user.getUserId();
                 AppUtlity.addLoginTimeStamp(userId);
             } finally {
                 // do whatever u want to do
             }
        }
    
    c) Now in any class like service or dao, you can easily get user login timestamp as below:
    
    Date date = AppUtlity.getUserLoginTimeStamp(userId);
    
    I hope this solution is feasible.