1.實現(xiàn)自定義的攔截器:
(1)實現(xiàn)HandlerInterceptor接口。
(2)繼承實現(xiàn)了HandlerInterceptor接口的類。比如Spring已經(jīng)提供的實現(xiàn)了HandlerInterceptor接口的抽象類HandlerInterceptorAdapter。
public interface HandlerInterceptor {
//在請求處理之前進行調(diào)用,該方法的返回值是Boolean類型的,當它返回為false時,表示請求結(jié)束,
//后續(xù)的Interceptor和Controller都不會再執(zhí)行;
//當返回值為true 時就會繼續(xù)調(diào)用下一個Interceptor的preHandle方法,
//如果已經(jīng)是最后一個Interceptor的時候就會是調(diào)用當前請求的Controller方法。
boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception;
//該方法會在Controller方法調(diào)用之后執(zhí)行,但是它會在DispatcherServlet進行視圖返回渲染之
//前被調(diào)用,并且只能是在當前所屬的Interceptor的preHandle方法的返回值為true時才能被調(diào)用。
void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception;
//該方法將在整個請求結(jié)束之后,也就是在DispatcherServlet 渲染了對應(yīng)的視圖之后執(zhí)行。
//這個方法的主要作用是用于進行資源清理工作的,
//并且只能是在當前所屬的Interceptor的preHandle方法的返回值為true時才能被調(diào)用。
void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception;
}
2.自定義實現(xiàn)
(1)實現(xiàn)HandlerInterceptor 接口
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
//在這里可以對參數(shù)做一些預(yù)處理和做一些驗證
return true;//方法給予執(zhí)行,就是允許controller的方法進行執(zhí)行
//false 不允許,可以在這之前在reponse中編寫返回的結(jié)果
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
//Controller執(zhí)行完畢后,返回之前,可以對request和reponse進行處理
//如果是前后端沒有分離,在進入View層中前執(zhí)行
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
//在一個請求處理完畢,即將銷毀的時候,執(zhí)行,可以做一些資源釋放之類的工作
}
}
(2)將攔截器加入配置中
@Configuration
public class MyConfig extends WebMvcConfigurerAdapter{
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/user/**");
}
}
3.執(zhí)行順序說明
- 首先按照執(zhí)行順序執(zhí)行所有攔截器的preHandle()方法,如果遇到返回值是false,則不會執(zhí)行還未執(zhí)行的攔截器,而是直接倒序執(zhí)行afterCompletion()方法,如果為true,則依次執(zhí)行剩下的攔截器;
- 如果所有攔截器的preHandle()方法返回值都為true,則執(zhí)行相應(yīng)的控制層接口(controller),如果在該接口中有異常拋出,則和preHandle()方法返回false一樣,不會執(zhí)行postHandle(),而是直接倒序執(zhí)行afterCompletion()方法;
- 如果接口(controller)中業(yè)務(wù)邏輯執(zhí)行完成(頁面還未渲染數(shù)據(jù)),會倒序執(zhí)行postHandle()方法,渲染完數(shù)據(jù)后,然后倒序執(zhí)行afterCompletton()方法。