我正在将基于 Spring XML 的配置迁移到基于 Java 的配置。下面的类实现了 HttpSessionListener 和 ApplicationContextAware,在 XML 配置下工作得很好。但是使用 Java 配置,启动 Tomcat 服务器时出现以下错误。
错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionListener' defined in com.grc.config.WebConfig: Initialization of bean failed; nested exception is java.lang.UnsupportedOperationException: Section 4.4 of the Servlet 3.0 specification does not permit this method to be called from a ServletContextListener that was not defined in web.xml, a web-fragment.xml file nor annotated with @WebListener
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:584)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
类别:
public class SessionListener implements HttpSessionListener,ApplicationContextAware {
private static final Logger logger = ExtendedLoggerFactory.getLogger(Info.HTTP_LOGGER);
@Autowired
private JdbcHSqlRepository jdbcHSqlRepository;
@Autowired
private LoginEventRepository loginEventRepo;
@SuppressWarnings("unused")
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
if(applicationContext instanceof WebApplicationContext) {
((WebApplicationContext)applicationContext).getServletContext().addListener(this);
}
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
httpSessionEvent.getSession().setMaxInactiveInterval(5*60);
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession httpSession = httpSessionEvent.getSession();
//mark user login event as looged out
LoginEventVO event = (LoginEventVO)httpSession.getAttribute(Constants.LOGIN_EVENT);
if(event != null) {
event.setActive(false);
loginEventRepo.saveAndFlush(event.transform());
}
logger.debug("Session destroyed : " + httpSession.getId());
jdbcHSqlRepository.dropSessionTables(httpSession);
}
}
当我尝试不实现 ApplicationContextAware 时,能够启动服务器而没有任何错误,但在执行 sessionDestroyed 方法时出现以下错误。
错误:
java.lang.NullPointerException: null
at com.grc.riskanalysis.interceptor.SessionListener.sessionDestroyed(SessionListener.java:45)
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:801)
at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:659)
at org.apache.catalina.session.ManagerBase.processExpires(ManagerBase.java:573)
at org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:558)
at org.apache.catalina.core.StandardContext.backgroundProcess(StandardContext.java:5474)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1398)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1402)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1402)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1370)
at java.lang.Thread.run(Thread.java:748)
Java 配置中我遗漏了什么吗?
@lucid 输入后,在 sessionDestroyed() 方法中手动注入(inject)所需的依赖项,效果很好。
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession httpSession = httpSessionEvent.getSession();
//mark user login event as looged out
LoginEventVO event = (LoginEventVO)httpSession.getAttribute(Constants.LOGIN_EVENT);
ApplicationContext ctx = WebApplicationContextUtils.
getWebApplicationContext(httpSession.getServletContext());
if(event != null) {
event.setActive(false);
if(loginEventRepo == null) {
this.loginEventRepo = (LoginEventRepository)
ctx.getBean("loginEventRepository");
}
loginEventRepo.saveAndFlush(event.transform());
}
logger.debug("Session destroyed : " + httpSession.getId());
if(jdbcHSqlRepository == null) {
this.jdbcHSqlRepository = (JdbcHSqlRepository)
ctx.getBean("jdbcHSqlRepository");
}
jdbcHSqlRepository.dropSessionTables(httpSession);
}
最佳答案
您可以像这样在应用程序中注册HttpSessionListener
。
删除 ApplicationContextAware
实现和相关方法
public class SessionListener implements HttpSessionListener {
// keep required code
}
现在,我们可以使用@WebListener
注解来注册并添加@ServletComponentScan
到主类中。 (如果是 Spring Boot 应用程序)
@Weblistener
public class SessionListener implements HttpSessionListener {
// keep required code
}
在非Springboot应用中,这样配置。
public class AnnotationWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) throws ServletException {
// other configs
container.addListener(SessionListener.class);
// other configs
}
As this is not spring managed bean, we need to manually inject dependencies. (make sure bean names are correct)
@Weblistener
public class SessionListener implements HttpSessionListener {
private LoginEventRepository loginEventRepo;
private JdbcHSqlRepository getJdbcHSqlRepository(HttpSessionEvent evt){
if(loginEventRepo != null) {
ApplicationContext ctx = WebApplicationContextUtils.
getWebApplicationContext(evt.getServletContext());
this.loginEventRepo = (LoginEventRepository)
ctx.getBean("loginEventRepo");
}
return this.loginEventRepo;
}
}
关于java - 出现类似 "java.lang.UnsupportedOperationException: Section 4.4 of the Servlet 3.0 specification does not permit this method to be called"的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59434595/