SPRing MVC也可以使用攔截器對請求進行攔截處理,用戶可以自定義攔截器來實現特定的功能,自定義的攔截器必須實現HandlerInterceptor接口:
preHandle():這個方法在業務處理器處理請求之前被調用,在該方法中對用戶請求 request 進行處理。如果程序員決定該攔截器對請求進行攔截處理后還要調用其他的攔截器,或者是業務處理器去進行處理,則返回true;如果程序員決定不需要再調用其他的組件去處理請求,則返回false。
postHandle():這個方法在業務處理器處理完請求后,但是DispatcherServlet向客戶端返回響應前被調用,在該方法中對用戶請求request進行處理。
afterCompletion():這個方法在DispatcherServlet 完全處理完請求后被調用,可以在該方法中進行一些資源清理的操作。
public classFirstInterceptor implements HandlerInterceptor{ /** * 該方法在目標方法之前被調用. * 若返回值為 true, 則繼續調用后續的攔截器和目標方法. * 若返回值為 false, 則不會再調用后續的攔截器和目標方法. * * 可以考慮做權限. 日志, 事務等. */ @Override public voidafterCompletion(HttpServletRequest arg0, HttpServletResponsearg1, Object arg2, Exception arg3) throws Exception { System.out.println("FirstInterceptor:afterCompletion"); } /** * 調用目標方法之后, 但渲染視圖之前. * 可以對請求域中的屬性或視圖做出修改. */ @Override public voidpostHandle(HttpServletRequest arg0, HttpServletResponse arg1, Objectarg2, ModelAndView arg3) throws Exception { System.out.println("FirstInterceptor:postHandle"); } /** * 在目標方法之前 * 若返回值為true,則繼續調用后續攔截器和目標方法 * 若返回值為false,則不會 */ @Override public booleanpreHandle(HttpServletRequest arg0, HttpServletResponse arg1, Objectarg2) throwsException { System.out.println("FirstInterceptor:preHandle"); return true; } }2. 攔截器方法執行順序

3. 配置自定義攔截器
<mvc:interceptors> <!-- 配置LocaleChanceInterceptor --> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean> <!-- 配置自定義攔截器 --> <bean class="spring.interceptors.FirstInterceptor"></bean> <!-- 配置攔截器(不)作用的路徑 --> <mvc:interceptor> <mvc:mapping path="/emps"/> <bean class="spring.interceptors.SecondInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>public classSecondInterceptor implements HandlerInterceptor{ @Override public booleanpreHandle(HttpServletRequest request, HttpServletResponseresponse, Object handler) throws Exception { System.out.println("[SecondInterceptor] preHandle"); return false; } @Override public void postHandle(HttpServletRequestrequest, HttpServletResponseresponse, Object handler, ModelAndViewmodelAndView) throwsException { System.out.println("[SecondInterceptor] postHandle"); } @Override public voidafterCompletion(HttpServletRequest request, HttpServletResponseresponse, Object handler, Exception ex) throws Exception { System.out.println("[SecondInterceptor] afterCompletion"); } }4.攔截器順序

十三、異常處理
1.異常處理
SpringMVC 通過HandlerExceptionResolver 處理程序的異常,包括 Handler 映射、數據綁定以及目標方法執行時發生的異常。
SpringMVC提供的 HandlerExceptionResolver 的實現類

2. HandlerExceptionResolver
DispatcherServlet默認裝配的 HandlerExceptionResolver:
沒有使用<mvc:annotation-driven/> 配置:

使用了<mvc:annotation-driven/> 配置– :

主要處理 Handler 中用 @ExceptionHandler注解定義的方法。
第一種方式:
@RequestMapping("/testExceptionHandlerExceptionResolver") public StringtestExceptionHandlerExceptionResolver(@RequestParam("i")inti){ System.out.println("result: "+ (10 / i)); return "success"; } /** * 1. 在@ExceptionHandler方法的入參中可以加入 Exception 類型的參數, 該參數即對應發生的異常對象 * 2. @ExceptionHandler方法的入參中不能傳入 Map. 若希望把異常信息傳導頁面上, 需要使用 ModelAndView 作為返回值 * 3. @ExceptionHandler方法標記的異常有優先級的問題. * 4. @ControllerAdvice: 如果在當前 Handler 中找不到@ExceptionHandler方法來出來當前方法出現的異常, * 則將去@ControllerAdvice標記的類中查找@ExceptionHandler標記的方法來處理異常. */ @ExceptionHandler({ArithmeticException.class}) public ModelAndViewhandleArithmeticException(Exception ex){ System.out.println("出異常了: " + ex); ModelAndViewmv = newModelAndView("error"); mv.addObject("exception",ex); return mv; } @ExceptionHandler 注解定義的方法優先級問題:
例如發生的是NullPointerException,但是聲明的異常有RuntimeException 和 Exception,此候會根據異常的最近繼承關系找到繼承深度最淺的那個@ExceptionHandler注解方法,即標記了 RuntimeException 的方法
ExceptionHandlerMethodResolver內部若找不到@ExceptionHandler 注解的話,會找
@ControllerAdvice 中的@ExceptionHandler注解方法
第二種方式(推薦):
@ControllerAdvicepublic classSpringMVCTestExceptionHandler { @ExceptionHandler({ArithmeticException.class}) public ModelAndViewhandleArithmeticException(Exception ex){ System.out.println("----> 出異常了: " + ex); ModelAndViewmv = newModelAndView("error"); mv.addObject("exception",ex); return mv; }}3. ResponseStatusExceptionResolver
在異常及異常父類中找到 @ResponseStatus注解,然后使用這個注解的屬性進行處理。定義一個@ResponseStatus 注解修飾的異常類
@ResponseStatus(value=HttpStatus.FORBIDDEN, reason="用戶名密碼不匹配!")public classUserNameNotMatchPassWordException extends RuntimeException{ private static final long serialVersionUID= 1L; } 若在處理器方法中拋出了上述異常:
若ExceptionHandlerExceptionResolver不解析述異常。由于觸發的異常UnauthorizedException 帶有@ResponseStatus注解。因此會被ResponseStatusExceptionResolver解析到。最后響應HttpStatus.UNAUTHORIZED 代碼給客戶
端。HttpStatus.UNAUTHORIZED 代表響應碼401,無權限。關于其他的響應碼請參考 HttpStatus 枚舉類型源碼。
//@ResponseStatus(reason="測試",value=HttpStatus.NOT_FOUND) @RequestMapping("/testResponseStatusExceptionResolver") public StringtestResponseStatusExceptionResolver(@RequestParam("i")inti){ if(i == 13){ throw newUserNameNotMatchPasswordException(); } System.out.println("testResponseStatusExceptionResolver..."); return "success"; }4. DefaultHandlerExceptionResolver
對一些特殊的異常進行處理,比如NoSuchRequestHandlingMethodException、
HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException等。
@RequestMapping(value="/testDefaultHandlerExceptionResolver",method=RequestMethod.POST) public StringtestDefaultHandlerExceptionResolver(){ System.out.println("testDefaultHandlerExceptionResolver..."); return "success"; }5. SimpleMappingExceptionResolver
如果希望對所有異常進行統一處理,可以使用
SimpleMappingExceptionResolver,它將異常類名映射為視圖名,即發生異常時使用對應的視圖報告異常
<!-- 配置使用 SimpleMappingExceptionResolver 來映射異常 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionAttribute" value="ex"></property> <property name="exceptionMappings"> <props> <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop> </props> </property> </bean> @RequestMapping("/testSimpleMappingExceptionResolver") public StringtestSimpleMappingExceptionResolver(@RequestParam("i")inti){ String[] vals = newString[10]; System.out.println(vals[i]); return "success"; }<h4>error page</h4> ${requestScope.ex }
源代碼文件:http://download.csdn.net/detail/QQ_26553781/9757893
新聞熱點
疑難解答