我想创建一个会话范围的bean来监视HTTP会话的激活和钝化。豆非常简单:
package my.log;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;
import org.apache.log4j.Logger;
public class SessionLoggingListenerBean implements HttpSessionActivationListener {
private final Logger LOG = Logger.getLogger(this.getClass());
public SessionLoggingListenerBean() {
LOG.info("SessionLoggingListenerBean starting");
}
public void init() {
LOG.info("SessionLoggingListenerBean init");
}
public void sessionDidActivate(HttpSessionEvent event) {
LOG.info("Session " + event.getSession().getId() + " activated");
}
public void sessionWillPassivate(HttpSessionEvent event) {
LOG.info("Session " + event.getSession().getId() + " will passivate");
}
}
应用程序上下文中的Bean定义:
<bean id="sessionLoggingListenerBean" class="my.log.SessionLoggingListenerBean" scope="session" init-method="init" lazy-init="false"/>
使用此配置,即使是构造函数或init()方法,也没有来自此类的日志。显然,Spring不会创建这个bean 通过反复试验,我检查了Spring在另一个bean需要时实例化这样一个bean,例如:用于UI。还有其他(更好)的方式吗?这是春天的错误吗? 使用的Spring版本:2.0.8。
答案 0 :(得分:2)
HttpSessionActivationListener
是javax.servlet.http
包的一部分。这应该给你一个提示,它应该由Servlet
容器管理。在您的情况下,您没有通过Listener
或ServletContext
向web.xml
注册SerlvetContainerInitializer
。
通过web.xml
,您将无法将其作为Spring和Servlet容器托管对象,因此存在这些变通方法,first,second。
如果您使用的是WebApplicationInitializer
,则可以实例化AnnotationConfigWebApplicationContext
,创建SessionLoggingListenerBean
bean,检索它并将其与
SessionLoggingListenerBean yourBean = context.getBean(SessionLoggingListenerBean.class);
servletContext.addListener(yourBean);
答案 1 :(得分:0)
经过一些实验后,我认为最好不要将Spring用于此目的。我已经修改了类来实现HttpSessionListener和Serializable:
public class SessionLoggingListener implements HttpSessionListener,
HttpSessionActivationListener, Serializable {
private static final long serialVersionUID = -763785365219658010L;
private static final Logger LOG = Logger.getLogger(SessionLoggingListener.class);
public SessionLoggingListener() {
LOG.info("SessionLoggingListener created");
}
public void sessionDidActivate(HttpSessionEvent event) {
LOG.info("Session " + event.getSession().getId() + " activated");
}
public void sessionWillPassivate(HttpSessionEvent event) {
LOG.info("Session " + event.getSession().getId() + " will passivate");
}
public void sessionCreated(HttpSessionEvent event) {
final HttpSession session = event.getSession();
LOG.info("Session " + session.getId() + " created. MaxInactiveInterval: " + session.getMaxInactiveInterval() + " s");
session.setAttribute(this.getClass().getName(), this);
}
public void sessionDestroyed(HttpSessionEvent event) {
LOG.info("Session " + event.getSession().getId() + " destroyed");
event.getSession().removeAttribute(this.getClass().getName());
}
}
并将其添加到web.xml:
<listener>
<listener-class>
evo.log.SessionLoggingListener
</listener-class>
</listener>
从现在开始,无论何时创建新会话,侦听器都会绑定它(session.setAttribute(...)
)。这是使容器注意到关于会话激活或钝化的监听器所必需的。
对于Spring和会话 - 根据此forum thread Spring在请求会话bean之前不加载会话bean:
会话bean被视为“原型”的特殊形式。这意味着它将在创建实例时遵循原型语义。
对我而言,这是一种不直观且没有很好记录的行为。