spring 全域性異常處理
spring3.0開發d異常處理,如果只有jsp請求能捕獲到異常,是不足夠的, 有時候AJAX返回json資料時遇到異常。這時候預設的處理方式不能滿足了, 需要自定義的方式支援同步和ajax非同步異常處理。
Spring3.0中對異常的處理方法一共提供了兩種:一種是使用HandlerExceptionResolver介面;一種是在Controller類內部使用@ExceptionHandler註解。使用第一種方式可以實現全域性異常控制,並且Spring已經提供了一個預設的實現類SimpleMappingExceptionResolver;使用第二種方式可以在Controller內部實現更個性化的異常處理方式,靈活性更高。一般來說,專案中只需要採用第一種方式就可以了,每個人都自己定義異常的展現方式,太過個性不統一。
以配置檔案的方式進行異常管理
在配置dispacher-servlet.xml
配置多個異常處理的地方。
以註解的方式配置異常管理
為了方便閱讀, 把程式碼發全一點
- @Controller
- public class ExceptionHandlerController
- {
- private final Logger log = LoggerFactory.getLogger(getClass());
- @ExceptionHandler(ManagerSecurityException.class)
- public ModelAndView handleManagerSecurityException(ManagerSecurityException e,
- HttpServletResponse response)
- throws IOException
- {
- log.info("Manager exception handler " + e.getMessage());
- response.sendError(HttpServletResponse.SC_FORBIDDEN,
- e.getMessage());
- return new ModelAndView("viewName",new HashMap());
- }
- }
這樣的配置處理jstl請求jsp沒有問題, 如果是jquery的 $.post的方法請求, 那麼如果還是返回 error.jsp ,那在 js的success函式里則不能很好地輸出顯示。
問題又來了: 如果在 handleManagerSecurityException方法的上面打上註解 @ResponeBody 那麼這樣又只能返回 json格式串的異常處理, 你想同步請求跳到到error.jsp又不行啦!
解決辦法是這樣的:定製化異常處理
下面我們來看看CustomSimpleMappingExceptionResolver.java是如何做到支援JSP和JSON格式返回的異常錯誤的
- @Override
- protected ModelAndView doResolveException(HttpServletRequest request,
- HttpServletResponse response,
- Object handler,
- Exception ex) {
- // Expose ModelAndView for chosen error view.
- String viewName = determineViewName(ex, request);
- if (viewName != null) {//JSP格式返回
- if(!(request.getHeader("accept").indexOf("application/json")>-1 || request.getHeader("X-Requested-With").indexOf("XMLHttpRequest")>-1)){//如果不是非同步請求
- // Apply HTTP status code for error views, if specified.
- // Only apply it if we're processing a top-level request.
- Integer statusCode = determineStatusCode(request, viewName);
- if (statusCode != null) {
- applyStatusCodeIfPossible(request, response, statusCode);
- return getModelAndView(viewName, ex, request);
- }
- }else{//JSON格式返回
- Map model=new HashMap();
- if(this.logger.isDebugEnabled()){
- model.put("debug", true);
- }//exception
- model.put(ConfigConstants.RESULT, ex.getMessage());
- model.put("failure", true);
- try {
- response.getWriter().write("有異常啦!");
- } catch (IOException e) {
- e.printStackTrace();
- }
- return new ModelAndView();
- }
- return null;
- }
- else {
- return null;
- }
- }
這裡判斷 request.getHeader("accept").indexOf("application/json") 是不是非同步請求
下面給出同步和非同步請求的Header
同步的text/html
=== MimeHeaders ===
host = localhost:8888
user-agent = Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
accept = text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-language = en,zh;q=0.7,en-gb;q=0.3
accept-encoding = gzip,deflate
accept-charset = ISO-8859-1,utf-8;q=0.7,*;q=0.7
keep-alive = 115
connection = keep-alive
cookie = JSESSIONID=BB7441E4B481FF64A5BCC8E6F596C330
非同步的application/json
=== MimeHeaders ===
host = localhost:8888
user-agent = Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
accept = application/json, text/javascript, */*
accept-language = en,zh;q=0.7,en-gb;q=0.3
accept-encoding = gzip,deflate
accept-charset = ISO-8859-1,utf-8;q=0.7,*;q=0.7
keep-alive = 115
connection = keep-alive
content-type = application/x-www-form-urlencoded
x-requested-with = XMLHttpRequest
referer =
cookie = JSESSIONID=A4B59EA87C9B83B71C0D455634746411
請注意
try {
response.getWriter().write("有異常啦!");
} catch (IOException e) {
e.printStackTrace();
}
return new ModelAndView();
關鍵就在最後這1句 return new ModelAndView();
為什麼不寫 return null; 或者 return new ModelAndView('jsonView', model); 呢?
因為spring3的原始碼裡這樣寫著了
- protected ModelAndView processHandlerException(HttpServletRequest request,
- HttpServletResponse response,
- Object handler,
- Exception ex) throws Exception {
- // Check registerer HandlerExceptionResolvers...
- ModelAndView exMv = null;
- for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
- exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
- if (exMv != null) {
- break;
- }
- }
- if (exMv != null) {
- if (exMv.isEmpty()) {
- return null;
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv,
- ex);
- }
- WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
- return exMv;
- }
- throw ex;
- }
注意看
if (exMv != null) {
if (exMv.isEmpty()) {
return null;
}
這句和最後一句: throw ex;
如果你寫 respone.getWriter().write("有異常啦"); 你也要 new一個空的ModelAndView,上面的程式碼表明, 如果你 return null; 它就跑出異常 throw ex; 如果沒人接收, 則會呼叫你配置的預設異常處理器 或者中斷不做任何輸出。
好了, 這樣可以同時支援同步和AJAX非同步請求異常處理了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-1820428/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Spring Cloud Gateway的全域性異常處理SpringCloudGateway
- Spring Boot 2 Webflux的全域性異常處理Spring BootWebUX
- spring-boot-route(四)全域性異常處理Springboot
- springboot全域性異常處理Spring Boot
- .netcore全域性異常處理NetCore
- ASP.NET 全域性異常處理ASP.NET
- SpringBoot之全域性異常處理Spring Boot
- NETCORE - 全域性異常處理(Exception)NetCoreException
- dotNet8 全域性異常處理
- springboot下新增全域性異常處理和自定義異常處理Spring Boot
- Spring Boot乾貨系列:(十三)Spring Boot全域性異常處理整理Spring Boot
- 設計一個全域性異常處理器
- SpringBoot處理全域性統一異常Spring Boot
- SpringBoot中的全域性異常處理Spring Boot
- 簡單的全域性異常統一處理
- SpringBoot優雅的全域性異常處理Spring Boot
- Vue3 如何實現全域性異常處理?Vue
- Django筆記三十一之全域性異常處理Django筆記
- spring boot 實現監聽器、過濾器、全域性異常處理Spring Boot過濾器
- 實戰Spring Boot 2.0系列(二) - 全域性異常處理和測試Spring Boot
- 【SpringBoot】全域性異常處理@ControllerAdviceSpring BootController
- Spring-全域性異常攔截Spring
- SpringBoot進行優雅的全域性異常處理Spring Boot
- Spring Boot 異常處理Spring Boot
- flex全域性異常Flex
- 聊聊springboot專案全域性異常處理那些事兒Spring Boot
- spring boot 全域性錯誤處理Spring Boot
- Spring Boot GraphQL 實戰 03_分頁、全域性異常處理和非同步載入Spring Boot非同步
- spring boot配置跨域、全域性異常處理、page分頁配置、統一返回MessageResultSpring Boot跨域
- 深入理解Spring異常處理Spring
- spring boot 統一異常處理Spring Boot
- Spring MVC統一異常處理SpringMVC
- NetCore實現全域性模型繫結異常資訊統一處理NetCore模型
- Spring系列(七) Spring MVC 異常處理SpringMVC
- 異常篇——異常處理
- wpf 捕獲全域性異常
- springmvc高可用響應物件以及全域性異常處理類的編寫SpringMVC物件
- 異常處理