Java 在所有web应用程序中管理要访问的会话属性
我有一些会话属性,所有应用程序(DAO、业务对象、bean等)都必须可以访问这些属性 我无法创建具有静态属性的类,因为静态属性共享给不同的会话 例如:用户在应用程序中登录,我需要保存登录时间,我需要将此值存储在会话属性中,因为在我的应用程序的某些点(如BO(业务对象))中,我需要知道用户何时登录应用程序 我无法在我的应用程序的某些地方访问HttpRequest,我需要一些其他解决方案Java 在所有web应用程序中管理要访问的会话属性,java,jsf,tomcat,web-applications,jsf-2,Java,Jsf,Tomcat,Web Applications,Jsf 2,我有一些会话属性,所有应用程序(DAO、业务对象、bean等)都必须可以访问这些属性 我无法创建具有静态属性的类,因为静态属性共享给不同的会话 例如:用户在应用程序中登录,我需要保存登录时间,我需要将此值存储在会话属性中,因为在我的应用程序的某些点(如BO(业务对象))中,我需要知道用户何时登录应用程序 我无法在我的应用程序的某些地方访问HttpRequest,我需要一些其他解决方案 编写一个POJO,其中包含您需要的所有“请求范围”属性,例如“登录时间” 写一篇: public PojoFil
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();
}
...
}
显然,这可以设计得更好,这样过滤器就不会泄漏到代码的其余部分,但这应该给你一个想法。你已经在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.