詳解Springboot自定義異常處理
背景
Springboot 默認把異常的處理集中到一個ModelAndView中了,但項目的實際過程中,這樣做,并不能滿足我們的要求。具體的自定義異常的處理,參看以下
具體實現(xiàn)
如果仔細看完spring boot的異常處理詳解,并且研究過源碼后,我覺得具體的實現(xiàn)可以不用看了。。。
重寫定義錯誤頁面的url,默認只有一個/error
@Bean public EmbeddedServletContainerCustomizer containerCustomizer(){ return new EmbeddedServletContainerCustomizer(){ @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error/404")); container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500")); container.addErrorPages(new ErrorPage(java.lang.Throwable.class,"/error/500")); } }; }
重寫通過實現(xiàn)ErrorController,重寫B(tài)asicErrorController的功能實現(xiàn)
/** * 重寫B(tài)asicErrorController,主要負責系統(tǒng)的異常頁面的處理以及錯誤信息的顯示 * @see org.springframework.boot.autoconfigure.web.BasicErrorController * @see org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration * * @author Jonathan * @version 2016/5/31 11:22 * @since JDK 7.0+ */ @Controller @RequestMapping(value = "error") @EnableConfigurationProperties({ServerProperties.class}) public class ExceptionController implements ErrorController { private ErrorAttributes errorAttributes; @Autowired private ServerProperties serverProperties; /** * 初始化ExceptionController * @param errorAttributes */ @Autowired public ExceptionController(ErrorAttributes errorAttributes) { Assert.notNull(errorAttributes, "ErrorAttributes must not be null"); this.errorAttributes = errorAttributes; } /** * 定義404的ModelAndView * @param request * @param response * @return */ @RequestMapping(produces = "text/html",value = "404") public ModelAndView errorHtml404(HttpServletRequest request, HttpServletResponse response) { response.setStatus(getStatus(request).value()); Map<String, Object> model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)); return new ModelAndView("error/404", model); } /** * 定義404的JSON數(shù)據(jù) * @param request * @return */ @RequestMapping(value = "404") @ResponseBody public ResponseEntity<Map<String, Object>> error404(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)); HttpStatus status = getStatus(request); return new ResponseEntity<Map<String, Object>>(body, status); } /** * 定義500的ModelAndView * @param request * @param response * @return */ @RequestMapping(produces = "text/html",value = "500") public ModelAndView errorHtml500(HttpServletRequest request, HttpServletResponse response) { response.setStatus(getStatus(request).value()); Map<String, Object> model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)); return new ModelAndView("error/500", model); } /** * 定義500的錯誤JSON信息 * @param request * @return */ @RequestMapping(value = "500") @ResponseBody public ResponseEntity<Map<String, Object>> error500(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)); HttpStatus status = getStatus(request); return new ResponseEntity<Map<String, Object>>(body, status); } /** * Determine if the stacktrace attribute should be included. * @param request the source request * @param produces the media type produced (or {@code MediaType.ALL}) * @return if the stacktrace attribute should be included */ protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) { ErrorProperties.IncludeStacktrace include = this.serverProperties.getError().getIncludeStacktrace(); if (include == ErrorProperties.IncludeStacktrace.ALWAYS) { return true; } if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) { return getTraceParameter(request); } return false; } /** * 獲取錯誤的信息 * @param request * @param includeStackTrace * @return */ private Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) { RequestAttributes requestAttributes = new ServletRequestAttributes(request); return this.errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace); } /** * 是否包含trace * @param request * @return */ private boolean getTraceParameter(HttpServletRequest request) { String parameter = request.getParameter("trace"); if (parameter == null) { return false; } return !"false".equals(parameter.toLowerCase()); } /** * 獲取錯誤編碼 * @param request * @return */ private HttpStatus getStatus(HttpServletRequest request) { Integer statusCode = (Integer) request .getAttribute("javax.servlet.error.status_code"); if (statusCode == null) { return HttpStatus.INTERNAL_SERVER_ERROR; } try { return HttpStatus.valueOf(statusCode); } catch (Exception ex) { return HttpStatus.INTERNAL_SERVER_ERROR; } } /** * 實現(xiàn)錯誤路徑,暫時無用 * @see ExceptionMvcAutoConfiguration#containerCustomizer() * @return */ @Override public String getErrorPath() { return ""; } }
總結(jié)
第一步,通過定義containerCustomizer,重寫定義了異常處理對應的視圖。目前定義了404和500,可以繼續(xù)擴展。
第二步,重寫B(tài)asicErrorController,當然可以直接定義一個普通的controller類,直接實現(xiàn)第一步定義的視圖的方法。重寫的目的是重用ErrorAttributes。這樣在頁面,直接可以獲取到status,message,exception,trace等內(nèi)容。
如果僅僅是把異常處理的視圖作為靜態(tài)頁面,不需要看到異常信息內(nèi)容的話,直接第一步后,再定義error/404,error/500等靜態(tài)視圖即可。
ErrorController根據(jù)Accept頭的內(nèi)容,輸出不同格式的錯誤響應。比如針對瀏覽器的請求生成html頁面,針對其它請求生成json格式的返回
以上兩步的操作,比網(wǎng)上流傳的更能實現(xiàn)自定義化。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot使用RabbitMQ延時隊列(小白必備)
這篇文章主要介紹了SpringBoot使用RabbitMQ延時隊列(小白必備),詳細的介紹延遲隊列的使用場景及其如何使用,需要的小伙伴可以一起來了解一下2019-12-12javaweb前端向后端傳值的幾種方式總結(jié)(附代碼)
javaweb是java開發(fā)中的一個方向,下面這篇文章主要給大家介紹了關(guān)于javaweb前端向后端傳值的幾種方式的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-03-03Java中資源加載的方法及Spring的ResourceLoader應用小結(jié)
在Java開發(fā)中,資源加載是一個基礎(chǔ)而重要的操作,這篇文章主要介紹了深入理解Java中資源加載的方法及Spring的ResourceLoader應用,本文通過實例代碼演示了通過ClassLoader和Class獲取資源的內(nèi)容,以及使用Spring的ResourceLoader加載多個資源的過程,需要的朋友可以參考下2024-01-01