1. 程式人生 > >SpringMVC之interceptor攔截器

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 {
    }
}