拦截器
Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口
- preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求 request 进行处理。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false。
- postHandle():这个方法在业务处理器处理完请求后,但是DispatcherServlet 向客户端返回响应前被调用,在该方法中对用户请求request进行处理。
- afterCompletion():这个方法在 DispatcherServlet 完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
配置文件中注册并配置自定义拦截器
Filter和拦截器的使用时机:
1)如果某些功能,需要其他组件的配合完成,就是用拦截器。因为拦截器是由Spring IoC容器负责实例化管理
Filter时有Tomcat服务器进行管理。一旦服务器启动,则web.xml配置文件中配置的Filter就已经创建好
拦截器运行原理:源码分析
try{
ModelAndView mv= null;
Object dispatchException= null;try{
processedRequest=this.checkMultipart(request);
multipartRequestParsed= processedRequest!= request;
mappedHandler=this.getHandler(processedRequest);if(mappedHandler== null){this.noHandlerFound(processedRequest, response);return;}
HandlerAdapter ha=this.getHandlerAdapter(mappedHandler.getHandler());
String method= request.getMethod();boolean isGet="GET".equals(method);if(isGet||"HEAD".equals(method)){long lastModified= ha.getLastModified(request, mappedHandler.getHandler());if((newServletWebRequest(request, response)).checkNotModified(lastModified)&& isGet){return;}}//运行prehandleif(!mappedHandler.applyPreHandle(processedRequest, response)){return;}
mv= ha.handle(processedRequest, response, mappedHandler.getHandler());if(asyncManager.isConcurrentHandlingStarted()){return;}this.applyDefaultViewName(processedRequest, mv);//运行posthandle
mappedHandler.applyPostHandle(processedRequest, response, mv);}catch(Exception var20){
dispatchException= var20;}catch(Throwable var21){
dispatchException=newNestedServletException("Handler dispatch failed", var21);}this.processDispatchResult(processedRequest, response, mappedHandler, mv,(Exception)dispatchException);}catch(Exception var22){this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);}catch(Throwable var23){this.triggerAfterCompletion(processedRequest, response, mappedHandler,newNestedServletException("Handler processing failed", var23));}
applyPreHandle:
booleanapplyPreHandle(HttpServletRequest request, HttpServletResponse response)throws Exception{for(int i=0; i<this.interceptorList.size();this.interceptorIndex= i++){
HandlerInterceptor interceptor=(HandlerInterceptor)this.interceptorList.get(i);if(!interceptor.preHandle(request, response,this.handler)){this.triggerAfterCompletion(request, response,(Exception)null);returnfalse;}}returntrue;}
privatevoidprocessDispatchResult(HttpServletRequest request, HttpServletResponse response,@Nullable HandlerExecutionChain mappedHandler,@Nullable ModelAndView mv,@Nullable Exception exception)throws Exception{boolean errorView=false;if(exception!= null){if(exceptioninstanceofModelAndViewDefiningException){this.logger.debug("ModelAndViewDefiningException encountered", exception);
mv=((ModelAndViewDefiningException)exception).getModelAndView();}else{
Object handler= mappedHandler!= null? mappedHandler.getHandler(): null;
mv=this.processHandlerException(request, response, handler, exception);
errorView= mv!= null;}}if(mv!= null&&!mv.wasCleared()){this.render(mv, request, response);if(errorView){
WebUtils.clearErrorRequestAttributes(request);}}elseif(this.logger.isTraceEnabled()){this.logger.trace("No view rendering, null ModelAndView returned.");}if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()){if(mappedHandler!= null){//执行aftercompletion
mappedHandler.triggerAfterCompletion(request, response,(Exception)null);}}}