Interceptor是SpringMVC中的拦截器,类似于Servlet中的Filter,主要针对Controller层进行拦截请求。
Interceptor的注册过程
在DispatcherServlet#doDispatch方法中的会调用getHandler方法(可接Controller查找部分),在这个方法里面会调用getHandlerExecutionChain方法,之后会遍历AbstractHandlerMapping.adaptedInterceptors,添加到chain中:
拦截器的调用主要在DispatcherServlet#doDispatch方法中,见applyPreHandle方法:
在这个方法中遍历HandlerExecutionChain.interceptorList中的拦截器对请求进行处理:
动态添加Interceptor
只要把自定义的Interceptor加到AbstractHandlerMapping.adaptedInterceptors中就完成了Interceptor的动态添加。
通过Context可以获取到RequestMappingHandlerMapping的Bean,而它又继承AbstractHandlerMapping类:
所以通过反射可以很方便地获取到adaptedInterceptors这个成员变量,然后直接加入即可:
@RequestMapping("/add")
public String addInterceptor() throws Exception {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assert attributes != null;
ServletContext servletContext = attributes.getRequest().getServletContext();
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
// 从IoC容器中获取bean
assert context != null;
RequestMappingHandlerMapping handlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Class<?> clazz = Class.forName("org.springframework.web.servlet.handler.AbstractHandlerMapping");
Field field = clazz.getDeclaredField("adaptedInterceptors");
field.setAccessible(true);
List interceptors = (List) field.get(handlerMapping);
interceptors.add(new MyInterceptor());
return "Add success";
}
}
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
PrintWriter writer = response.getWriter();
writer.write("This is MyInterceptor\n");
writer.flush();
writer.close();
return true;
}
}