這兩天遇到一個需求:在請求action時,校驗一下簽名的有效性。為了做到統一,在一處地方做校驗而不是分散在各個action里做,就用到了攔截器。個人覺得spring mvc中的攔截器和asp.net里面的HttpModule非常類似,都可以在請求在匹配到action之前做攔截。其他的不多說,直接上干貨。
這篇講基於java config的攔截器的實現,具體怎么做呢,其實非常簡單,只要兩步就可以完成,最后我會附上源代碼:
第一步:自定義攔截器。具體來說就是寫一個實現HandlerInterceptor接口的類,這個接口有三個方法,三個方法的執行時機不同,可以根據自己的需求看看實現哪一個。
@Component
public class SystemInterceptor implements HandlerInterceptor {
org.slf4j.Logger logger = LoggerFactory.getLogger("interceptor");
/**
* preHandle方法是進行處理器攔截用的,顧名思義,該方法將在Controller處理之前進行調用,
* SpringMVC中的Interceptor攔截器是鏈式的,可以同時存在多個Interceptor,
* 然后SpringMVC會根據聲明的前后順序一個接一個的執行,
* 而且所有的Interceptor中的preHandle方法都會在Controller方法調用之前調用。
* SpringMVC的這種Interceptor鏈式結構也是可以進行中斷的,
* 這種中斷方式是令preHandle的返回值為false,當preHandle的返回值為false的時候整個請求就結束了。
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
logger.error("攔截的Controller:"+handlerMethod.getBeanType().getName());
logger.error("攔截的action:"+handlerMethod.getMethod().getName());
return true;
}
/**
* 這個方法只會在當前這個Interceptor的preHandle方法返回值為true的時候才會執行。
* postHandle是進行處理器攔截用的,它的執行時間是在處理器進行處理之 后, 也就是在Controller的方法調用之后執行,
* 但是它會在DispatcherServlet進行視圖的渲染之前執行,也就是說在這個方法中你可以對ModelAndView進行操作。
* 這個方法的鏈式結構跟正常訪問的方向是相反的,也就是說先聲明的Interceptor攔截器該方法反而會后調用,
* 這跟Struts2里面的攔截器的執行過程有點像,
* 只是Struts2里面的intercept方法中要手動的調用ActionInvocation的invoke方法,
* Struts2中調用ActionInvocation的invoke方法就是調用下一個Interceptor或者是調用action,
* 然后要在Interceptor之前調用的內容都寫在調用invoke之前,要在Interceptor之后調用的內容都寫在調用invoke方法之后。
*/
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
/**
* 該方法也是需要當前對應的Interceptor的preHandle方法的返回值為true時才會執行。
* 該方法將在整個請求完成之后,也就是DispatcherServlet渲染了視圖執行, 這個方法的主要作用是用於清理資源的,
*/
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
第二步:注冊自定義攔截器。這一步是基於《基於JavaConfig配置的Spring MVC的構建》完成的,so,請先看下這篇文章,然后就會明白這一切都那么簡單~~。這里就一個方法,看一下就明白了,就只說下addPathPatterns的作用,這個方法的作用就是過濾請求的path,只有符合條件的請求path才會被攔截。
@Configuration
@EnableWebMvc
@ComponentScan("com.deepbatis.web")
public class WebConfig extends WebMvcConfigurerAdapter {
/*配置視圖解析器*/
@Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
/*注冊攔截器*/ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SystemInterceptor()).addPathPatterns("/*"); }
/*配置靜態資源的處理*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}

最后,跑一下程序就知道是怎么回事了,老樣子,放源碼: 攔截器的源碼在這里
