問題:本週在把現有專案整合shiro,問題是前端使用的是angularjs,如果對於單個的Controller,失敗後可以直接在程式碼塊中做try-catch來捕獲異常,進而返回給頁面或者是ajax的請求,來說明是不成功的。但是現在遇到一個問題是現有的模組以及功能已經有很多了,想要一個個加上try-catch,比較麻煩,於是思考是否有一個全域性處理異常的操作。進過查詢發現有一個org.springframework.web.servlet.HandlerExceptionResolver這個樣一個定義異常處理的介面。

解決方案

(1)自定義或者使用spring自帶的各種異常處理器

例如spring基於註解的異常解析器AnnotationHandlerMethodExceptionResolver 或者是spring自帶全域性異常處理器SimpleMappingExceptionResolver、自定義實現spring的全域性異常解析器HandlerExceptionResolver來處理。

       AnnotationHandlerMethodExceptionResolver目前我所知道的是需要在方法上定義異常的型別,如果異常型別多了,寫起程式碼太麻煩,所以我認為不好用。(那位大俠知道不用定義異常型別就處理所有異常,可以留言告訴我,謝謝!)

       spring自帶全域性異常處理器SimpleMappingExceptionResolver也是比較繁瑣的,我在專案中配置了,發現在捕獲shiro的沒有許可權的異常的時候,只能做redirect這樣的重定向之類。但是我又不想做跳轉(或者說是沒有辦法做跳轉,因為註解是@responseBody這樣的),最後只能放棄該方法。

       自定義實現spring的全域性異常解析器HandlerExceptionResolver來處理我認為是最方便的,當然,這個是針對當前的業務場景而言,並非絕對的。

(2)自定義實現spring的全域性異常解析器HandlerExceptionResolver

1.需要在spring-mvc.xml中配置如下bean,定義一個全域性異常處理類
2.實現介面
2.1:返回json資料,使用ajax請求的比較適合
public class CustomExceptionResolver implements HandlerExceptionResolver {

	Logger logger = LoggerFactory.getLogger(CustomExceptionResolver.class);

	/**
	 * <p>Title: resolveException</p>
	 * <p>Description: </p>
	 * @param request
	 * @param response
	 * @param handler
	 * @param ex 系統 丟擲的異常
	 * @return
	 */
	@Override
	public ModelAndView resolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		//handler就是處理器介面卡要執行Handler物件(只有method)
		//列印異常堆疊
		ex.printStackTrace();
		//錯誤資訊
		String msg= "";
		CustomException customException = null;
		if(ex instanceof CustomException){
			customException = (CustomException)ex;
		}else if(ex instanceof AuthorizationException){
			customException = new CustomException("沒有選單的許可權,請聯絡管理員!");
		}else{
			customException = new CustomException("系統發生異常,請聯絡管理員!");
		}

		msg = customException.getMessage();	
		ResultMsg result=ResultMsg.build(ResultMsg.FAIL_CODE, msg);;
		FrontEndHelper.responseOutWithJson(response,result);
	
		return null;
	}

}
我的具體的FrontEnHelper.responseOutWithJson(response, result);的實現方式如下,其實就是往輸出流返回一個json資料:
	/** 
	 * 以JSON格式輸出 
	 * @param response 
	 */  
	public static void responseOutWithJson(HttpServletResponse response,  
	        Object Object) {  
		String json=JsonUtils.objectToJson(Object);  
	    response.setCharacterEncoding("UTF-8");  
	    response.setContentType("application/json; charset=utf-8");  
	    PrintWriter out = null;  
	    try {  
	        out = response.getWriter();  
	        out.append(json);  
	        logger.info("返回json資料=【"+json+"】");  
	    } catch (IOException e) {  
	        e.printStackTrace();  
	    } finally {  
	        if (out != null) {  
	            out.close();  
	        }  
	    }  
	}
2.2:返回一個modelAndView,適合跳轉到一個錯誤頁面,此時需要在web.xml中配置錯誤地址,比如是500錯誤,那就配置500,然後會跳轉到error_500的地址,等等。
<error-page>  
    <exception-type>java.lang.Throwable</exception-type>  
    <location>/error_500</location>  
</error-page>  
<error-page>  
    <exception-type>java.lang.Exception</exception-type>  
    <location>/error_404</location>  
</error-page>  
<error-page>  
    <error-code>500</error-code>  
    <location>/error_500</location>  
</error-page>  

最後,配置了地址,別忘了你自己要寫一個請求該500或者是404地址的controller哦!