異常處理
異常處理器需要實作HandlerExceptionResolver接口,重寫resolveException方法
異常處理在服務端代碼産生異常後,用于在頁面友好提示,而不是顯示大堆異常資訊
自定義異常類
/**
* @Author Figo
* @Date 2019/12/5 23:03
* 自定義異常類
*/
public class SysException extends Exception{
// 存儲提示資訊的
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public SysException(String message) {
this.message = message;
}
}
/**
* @Author Figo
* @Date 2019/12/5 23:05
* 異常處理器
*/
public class SysExceptionResolver implements HandlerExceptionResolver {
/**
* 處理異常業務邏輯,當控制器抛出異常後,會進入異常處理類執行
* @param request
* @param response
* @param handler
* @param ex
* @return
*/
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
// 擷取到異常對象
SysException e = null;
if(ex instanceof SysException){
e = (SysException)ex;
}else{
e = new SysException("系統正在維護....");
}
// 建立ModelAndView對象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",e.getMessage());
mv.setViewName("error");
return mv;
}
}
在springmvc.xml中配置異常處理器
<!--配置異常處理器-->
<bean id="sysExceptionResolver" class="cn.figo.exception.SysExceptionResolver"/>
在控制器中抛出異常
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testException")
public String testException() throws SysException {
System.out.println("testException執行了...");
try {
// 模拟異常
int a = 10/0;
} catch (Exception e) {
// 列印異常資訊
e.printStackTrace();
// 抛出自定義異常資訊
throw new SysException("查詢所有使用者出現錯誤了...");
}
return "success";
}
}
當自造異常時,由于配置了異常處理器,将跳轉到error頁面,而不顯示異常資訊

同時這個例子由于配置了攔截器,是以在執行控制器方法之前執行了攔截器中的方法
攔截器
Spring MVC 的處理器攔截器類似于 Servlet 開發中的過濾器 Filter,用于對處理器進行預處理和後處理。
使用者可以自己定義一些攔截器來實作特定的功能。
攔截器鍊(Interceptor Chain),攔截器鍊就是将攔截器按一定的順序聯結成一條鍊。
在通路被攔截的方法或字段時,攔截器鍊中的攔截器就會按其之前定義的順序被調用。
過濾器和攔截器的差別:過濾器是 servlet 規範中的一部分, 任何 java web 工程都可以使用。
攔截器是 SpringMVC 架構自己的,隻有使用了 SpringMVC 架構的工程才能用。
過濾器在 url-pattern 中配置了/*之後,可以對所有要通路的資源攔截。
攔截器它是隻會攔截通路的控制器方法,如果通路的是 jsp, html,css,image 或者 js 是不會進行攔截的。
攔截器是 AOP 思想的具體應用。在定義攔截器,需要實作HandlerInterceptor接口,重寫preHandle、postHandle、afterCompletion方法。
preHandle:預處理,在controller方法執行前執行。此方法的執行時機是在控制器方法執行之前,是以我們通常是使用此方法對請求部分進行增強。 同時由于結果視圖還沒有建立生成,是以此時我們可以指定響應的視圖。
傳回值true放行,執行下一個攔截器,如果沒有,執行controller中的方法。
傳回值false不放行
postHandle:後處理方法,在controller方法執行後,success.jsp執行之前執行此方法的執行時機是在控制器方法執行之後, 結果視圖建立生成之前。是以通常是使用此方法對響應部分進行增強。因為結果視圖沒有生成,是以我們此時仍然可以控制響應結果。
afterCompletion:success.jsp頁面執行後,該方法會執行。此方法的執行時機是在結果視圖建立生成之後,展示到浏覽器之前。是以此方法執行時,本次請求要準備的資料具已生成完畢,且結果視圖也已建立完成,是以我們可以利用此方法進行清理操作。同時,我們也無法控制響應結果集内容。
自定義攔截器,要求必須實作: HandlerInterceptor 接口。/**
* 自定義攔截器
*/
public class MyInterceptor1 implements HandlerInterceptor {
/**
* 預處理,controller方法執行前
* return true 放行,執行下一個攔截器,如果沒有,執行controller中的方法
* return false不放行
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1執行了...前1111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
return true;
}
/**
* 後處理方法,controller方法執行後,success.jsp執行之前
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1執行了...後1111");
// request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
}
/**
* success.jsp頁面執行後,該方法會執行
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor1執行了...最後1111");
}
}
在springmvc.xml中配置攔截器
<!--配置攔截器-->
<mvc:interceptors>
<!--配置攔截器-->
<mvc:interceptor>
<!--要攔截的具體的方法-->
<mvc:mapping path="/user/*"/>
<!--不要攔截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置攔截器對象-->
<bean class="cn.figo.interceptor.MyInterceptor1" />
</mvc:interceptor>
</mvc:interceptors>
在定義了攔截器之後,我們可以看到執行順序
如果再配置一個攔截器形成攔截器鍊
<!--配置第二個攔截器-->
<mvc:interceptor>
<!--要攔截的具體的方法-->
<mvc:mapping path="/**"/>
<!--不要攔截的方法
<mvc:exclude-mapping path=""/>
-->
<!--配置攔截器對象-->
<bean class="cn.figo.interceptor.MyInterceptor2" />
</mvc:interceptor>
輸出如下,道理就是,先進者後出