SpringMVC之interceptor攔截器
Interceptor攔截器
一、概念
攔截器是SpringMVC中的一個強大控制元件,它可以在進入處理器之前做一些操作,或者在處理器完成後進行操作,甚至是在渲染檢視後進行操作。
二、攔截器定義
Spring要求處理器的攔截器都要實現org.springframework.web.servlet.HandlerInterceptor ,這個介面定義了3個方法:
(1)preHandle:在處理器之前執行的前置方法。返回一個boolean值,會影響後面的處理流程。
(2)postHandle:在處理器之後執行的後置方法,處理器的邏輯完成後執行它。
(3)afterCompletion:無論是否產生異常都會在渲染檢視後執行的方法。
三、攔截器的執行流程(鏈路回撥思想)
(1)進入前置方法(preHandle)
(2)前置方法的boolean是否為true; 若為false,直接(7);若為true,執行(3);
(3)進入處理器handler
(4)進入後置方法(postHandle)
(5)檢視解析和渲染圖
(6)進入完成方法(afterCompletion)
(7)結束
四、多個攔截器執行的順序
正常情況下,Spring會先從第一個攔截器開始進入前置方法,這樣前置方法是按配置順序執行的,然後執行處理器的程式碼,最後執行後置方法。後置方法和完成方法是按照配置順序逆序執行的,這和責任鏈模式的執行順序是一直的。
五、使用者登入的攔截器開發
1、通行攔截器
(1)重寫preHandle:從httpServletRequest中監測cookies資料,如果能夠獲取當前使用者的ticket(門票,儲存使用者登入狀態的資料),就將這個資料寫入臨時的ticket。接著判斷這個ticket是否在資料庫中,是否已經過期,登入狀態是否正常。驗證成功後返回true,並將這個使用者寫入hostHolder,讓此時的執行緒儲存這個使用者的登入資訊,最後返回true進入處理器。
(2)重寫postHandle:在處理器執行完後,將hostHolser的使用者填充到modelAndView中。
(3)重寫afterCompletion:最後將hostHolder清除掉。
@Component
public class PassportInterceptor implements HandlerInterceptor {
@Autowired
private LoginTicketDAO loginTicketDAO;
@Autowired
private UserDAO userDAO;
@Autowired
private HostHolder hostHolder;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
String ticket = null;
if (httpServletRequest.getCookies() != null) {
for (Cookie cookie : httpServletRequest.getCookies()) {
if (cookie.getName().equals("ticket")) {
ticket = cookie.getValue();
break;
}
}
}
if (ticket != null) {
LoginTicket loginTicket = loginTicketDAO.selectByTicket(ticket);
if (loginTicket == null || loginTicket.getExpired().before(new Date()) || loginTicket.getStatus() != 0) {
return true;
}
User user = userDAO.selectById(loginTicket.getUserId());
hostHolder.setUser(user);
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
if (modelAndView != null && hostHolder.getUser() != null) {
modelAndView.addObject("user", hostHolder.getUser());
}
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
hostHolder.clear();
}
}
2、登入攔截器
重寫preHandle:如果檢測到hostHolder為空,即使用者沒有登入,就將頁面跳轉到登入頁面,return false,先登入。
@Component
public class LoginRequiredInterceptor implements HandlerInterceptor {
@Autowired
private HostHolder hostHolder;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
if (hostHolder.getUser() == null) {
httpServletResponse.sendRedirect("/?pop=1");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}