記錄編寫監聽器時無法通過’@Autowired‘獲取業務類的問題
<listener>
<listener-class>com.netvour.commons.listener.SessionListener</listener-class>
</listener>但等我真正應用到這監聽器卻一直報空指標異常,debug後才發現,原來
@Autowired
private SysUserService sysUserService;
拿到的是null,上網查了才知道,監聽器是屬於servlet容器的,而不是spring 管理的, 無法通過應用spring的註解去引入業務類物件(-_-|||)~~
既然知道問題了,接下來就是找解決方式了。 直接在實現一個介面,ServletContextListener介面,它能夠監聽 ServletContext 物件的生命週期,實際上就是監聽 Web 應用的生命週期。
ServletContextListener有兩個方法需要重寫(實現),一個是contextInitialized(ServletContextEvent sce)方法,當Servlet 容器啟動Web 應用時呼叫該方法。在呼叫完該方法之後,容器再對Filter 初始化,並且對那些在Web 應用啟動時就需要被初始化的Servlet 進行初始化;一個是contextDestroyed(ServletContextEvent sce)方法,當Servlet 容器終止Web 應用時呼叫該方法。(在呼叫該方法之前,容器會先銷燬所有的Servlet 和Filter 過濾器)。
而我們需要做的就是,在contextInitialized(ServletContextEvent sce)中,獲取到業務類物件,程式碼如下:
public class SessionListener implements ServletContextListener,HttpSessionListener{
private SysUserService sysUserService;
@Override
public void sessionCreated(HttpSessionEvent se) {}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
//業務方法
SysUserLoginVo so = (SysUserLoginVo) se.getSession().getAttribute("user");
if(so!=null){
SysUserLoginVo tmp = new SysUserLoginVo();
tmp.setStatus(2);
boolean flag = sysUserService.updateSysUserInfo("listener",tmp);
if(flag){
System.out.println("session過期,自動更新使用者狀態成功");
}else{
System.out.println("session過期,自動更新使用者狀態失敗");
}
}
}
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
ApplicationContext context = (ApplicationContext) servletContext.getAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
//initialize service when spring context initialized,
//建立對應的service當spring上下文初始化之後
//使用spring框架中已經初始化的sysUserService
sysUserService = (SysUserService)context.getBean(SysUserService.class);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {}
}