詳解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,重寫定義了異常處理對應(yīng)的視圖。目前定義了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)容,輸出不同格式的錯誤響應(yīng)。比如針對瀏覽器的請求生成html頁面,針對其它請求生成json格式的返回
以上兩步的操作,比網(wǎng)上流傳的更能實現(xiàn)自定義化。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
記一次集成swagger2(Knife4j)在線文檔提示:Knude4j文檔請求異常的解決辦法
Knife4j是一個集Swagger2 和 OpenAPI3為一體的增強解決方案,下面這篇文章主要給大家介紹了關(guān)于一次集成swagger2(Knife4j)在線文檔提示:Knude4j文檔請求異常的解決辦法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-02-02
Java?Mybatis的初始化之Mapper.xml映射文件的詳解
這篇文章主要介紹了Java?Mybatis的初始化之Mapper.xml映射文件的詳解,解析完全局配置文件后接下來就是解析Mapper文件了,它是通過XMLMapperBuilder來進行解析的2022-08-08
解決springcloud阿里云OSS文件訪問跨域問題的實現(xiàn)
本文主要介紹了解決springcloud阿里云OSS文件訪問跨域問題的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06
SpringBoot中定時任務(wù)@Scheduled注解的使用解讀
這篇文章主要介紹了SpringBoot中定時任務(wù)@Scheduled注解的使用解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
SpringCloud Feign Jackson自定義配置方式
這篇文章主要介紹了SpringCloud Feign Jackson自定義配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringBatch數(shù)據(jù)寫入實現(xiàn)
Spring Batch通過ItemWriter接口及其豐富的實現(xiàn),提供了強大的數(shù)據(jù)寫入能力,本文主要介紹了SpringBatch數(shù)據(jù)寫入實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2025-04-04

