Jakarta ee 如果上一个会话已处于活动状态(如果用户忘记注销),请使用JAAS删除该会话
让下面的类成为会话范围的CDI托管beanJakarta ee 如果上一个会话已处于活动状态(如果用户忘记注销),请使用JAAS删除该会话,jakarta-ee,servlets,jaas,java-ee-7,jdbcrealm,Jakarta Ee,Servlets,Jaas,Java Ee 7,Jdbcrealm,让下面的类成为会话范围的CDI托管bean @Named @SessionScoped public class SessionUtils implements Serializable { private Map<String, Object>sessionMap; private static final long serialVersionUID=1l; public SessionUtils() {} @PostConstruct
@Named
@SessionScoped
public class SessionUtils implements Serializable
{
private Map<String, Object>sessionMap;
private static final long serialVersionUID=1l;
public SessionUtils() {}
@PostConstruct
private void init() {
sessionMap=new HashMap<String, Object>();
}
public Map<String, Object> getSessionMap() {
return sessionMap;
}
}
我需要调用以下HttpSessionBindingListener
public final class User implements HttpSessionBindingListener {
private static final Map<UserTable, HttpSession> logins = new HashMap<UserTable, HttpSession>();
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("valueBound() called.");
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("valueUnbound() called.");
}
}
但是,如果将User
的一个实例简单地存储到会话映射中(在该cdibean中),它们就不会被调用
JAAS/CDI中是否有其他方法来处理相同的问题—模拟HttpSessionBindingListener
我想做的是:如果用户忘记注销,那么在他/她下次尝试登录时,应该删除(上一次仍处于活动状态)会话
另外一件事:
UserTable
(不是User
——它只是一个示例。)是一个实际的JPA实体类。HttpSessionBindingListener
需要在JPA实体上实现,而JPA实体又需要从javax.servlet
包中获得对服务层的额外依赖,这不必要地增加了模块之间的耦合
这是否可以隔离开来,以便在web层上实现HttpSessionBindingListener
(无论JPA实体类-UserTable
是否仍为该类服务,即当UserTable
的实例放入会话时,valueBound()当从HttpSession
中删除UserTable
的一个实例时,将调用方法…并且valueUnbound()
,替换为另一个会话属性,或者会话本身被销毁/无效)?我希望在高级JavaEE中有一些方法
题目没有应有的意义。我将在以后编辑它,当我设想一个更有意义的标题时,或者如果您愿意,您可以在此之前自愿编辑它。据我所知,问题是,为什么只有在您调用request.getSession()
时才会调用HttpSessionBindingListener
只有当您调用request.getSession()
时,会话才会被创建,因此监听器被调用。
所以您需要调用该方法来启动会话,否则,如果您稍后在请求期间调用该方法,会话将启动
顺便说一下,在静态变量中存储HttpSession
是一种不好的做法,如果您“忘记”删除它,可能会导致内存泄漏
为了实现您想要做的事情,我将只在会话侦听器中存储一组静态的request.getSession().getId()
。在过滤器中,我将检查集合是否有这样的id
,这样您将获得一个现有会话或创建一个新会话。
或者,如果您确实需要知道会话属于哪个用户,则仍然存储在map中
如果用户忘记注销,则(上一个仍处于活动状态)会话
应在他/她下次尝试登录时删除
我通常只需在呈现登录页面时放弃“当前”会话:
request.getSession().invalidate();
换句话说,进入登录页面意味着退出当前会话。实际上,当HttpSessionBindingListener
的一个实现实例被设置为会话属性并且调用了valueUnbound()
方法时,调用了HttpSessionBindingListener
的重写方法valueUnbound(),当其实现的实例从会话中删除、替换为另一个属性或会话本身被销毁/失效时。会话实际上已经创建(当客户端发送第一个请求时)。我正在寻找一种方法来调用这些方法,而不必公开HttpSession
,比如request.getSession()
(因为我使用的是CDIBeans)并删除服务层上的javax.servlet.*
API的额外依赖项,因为实体类在需要实现此接口的服务层(EJB模块)上可用。对该层的这种依赖意味着模块之间的紧密耦合。无论如何,感谢您花时间讨论这个问题:)我将使用HttpSessionAttributeListener
,因为当您将User
设置为属性时,而不仅仅是在创建会话时,将调用它。然后使用@ApplicationScoped
bean存储UserId
到SessionId
的映射。需要注意的是,如果需要扩展到单个服务器之外,则需要某种外部存储来处理UserId
/SessionId
映射,但这需要在与用户相关联的实体类(User
)上实现HttpSessionAttributeListener
)。实体类在服务层上可用,这反过来需要来自javax.servlet
API的额外依赖,这是不正确的,并且增加了模块之间的耦合-服务层上的EJB不一定是本地的(如@local
所示)。它们可以是部署在单独服务器上的远程EJB,只有在添加了单独的库的情况下才能获取javax.servlet
包javax.servlet
是一个web层的东西,服务层应该不知道。不需要在实体类上实现侦听器类HttpSessionaDistributeListener
,用@WebListener
正确注释,在web层上是独立的,仅在会话映射中添加或删除用户
(或任何类)对象时侦听。在这种情况下,分离很容易保持。使用远程EJB进行会话管理当然是可以做到的,但在操作上会很复杂且成本高昂。使用memcached之类的工具会更简单、更具可扩展性。在放弃当前用户的会话之前,需要验证正在登录的用户是否已经有一个活动HTTP会话,该会话将导致维护一个用户会话列表。这个问题暗示着这类事情。对于e
request.getSession().setAttribute("newUser", new User()); //Or remove
sessionMap.put("newUser", new User());
request.getSession().invalidate();