日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Spring Boot错误处理机制以及定制自己的错误页面

發(fā)布時間:2025/4/16 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Boot错误处理机制以及定制自己的错误页面 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在我們使用Spring Boot的過程中肯定有遇到過發(fā)生錯誤的時候,這個時候可能頁面上出現(xiàn)的就是Spring Boot默認(rèn)的錯誤界面,有的時候我們希望能顯示我們自己設(shè)置的錯誤界面,或者攜帶我們自己的錯誤響應(yīng)參數(shù),比如查詢用戶是否存在的時候,如果用戶不存在,控制器可以選擇拋出一個用戶不存在異常,這個時候我們希望錯誤響應(yīng)參數(shù)可以攜帶一個message響應(yīng)參數(shù)表示用戶不存在,而不是Spring Boot為我們配置好的那幾個參數(shù),這個時候我們應(yīng)該這么做呢,這就是本文的目的。

如果要配置自己的錯誤界面,首先我們需要先了解一下Spring Boot是如何處理錯誤的。Spring Boot在自動配置類ErrorMvcAutoConfiguration中為我們添加了4個錯誤處理相關(guān)的組件,具體可以在IDEA中使用Ctrl+N來查找這個類,他們的作用可以查看下面代碼中的注釋:

1、DefaultErrorAttributes

//幫我們設(shè)置錯誤響應(yīng)參數(shù); @Override public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,boolean includeStackTrace) {Map<String, Object> errorAttributes = new LinkedHashMap<String, Object>();errorAttributes.put("timestamp", new Date());addStatus(errorAttributes, requestAttributes);addErrorDetails(errorAttributes, requestAttributes, includeStackTrace);addPath(errorAttributes, requestAttributes);return errorAttributes; }

2、BasicErrorController

//處理/error請求,根據(jù)請求頭中的信息(Accept參數(shù))來判斷優(yōu)先返回html頁面,還是JSON數(shù)據(jù) @Controller @RequestMapping("${server.error.path:${error.path:/error}}") public class BasicErrorController extends AbstractErrorController {@RequestMapping(produces = "text/html")//產(chǎn)生html類型的數(shù)據(jù);瀏覽器發(fā)送的請求來到這個方法處理public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {HttpStatus status = getStatus(request);Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));response.setStatus(status.value());//去哪個頁面作為錯誤頁面;包含頁面地址和頁面內(nèi)容ModelAndView modelAndView = resolveErrorView(request, response, status, model);return (modelAndView == null ? new ModelAndView("error", model) : modelAndView);}@RequestMapping@ResponseBody //產(chǎn)生json數(shù)據(jù),其他客戶端來到這個方法處理;public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {Map<String, Object> body = getErrorAttributes(request,isIncludeStackTrace(request, MediaType.ALL));HttpStatus status = getStatus(request);return new ResponseEntity<Map<String, Object>>(body, status);} }

3、ErrorPageCustomizer

/** 配置錯誤發(fā)生后,到哪去。這里是系統(tǒng)出現(xiàn)錯誤以后來到error請求進(jìn)行處理; 也就是到上面的BasicErrorController處理器,(相當(dāng)于以前web.xml注冊的錯誤頁面規(guī)則)。 可以看到這個參數(shù)是可配置的。 **/ @Value("${error.path:/error}") private String path = "/error";

4、DefaultErrorViewResolver

@Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status,Map<String, Object> model) {ModelAndView modelAndView = resolve(String.valueOf(status), model);if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);}return modelAndView; }private ModelAndView resolve(String viewName, Map<String, Object> model) {//默認(rèn)SpringBoot可以去找到一個頁面? 比如error/404String errorViewName = "error/" + viewName;//模板引擎可以解析這個頁面地址就用模板引擎解析TemplateAvailabilityProvider provider = this.templateAvailabilityProviders.getProvider(errorViewName, this.applicationContext);if (provider != null) {//模板引擎可用的情況下返回到errorViewName指定的視圖地址return new ModelAndView(errorViewName, model);}//模板引擎不可用,就在靜態(tài)資源文件夾下找errorViewName對應(yīng)的頁面error/404.htmlreturn resolveResource(errorViewName, model); }

錯誤響應(yīng)步驟如下:

一但系統(tǒng)出現(xiàn)4xx或者5xx之類的錯誤;ErrorPageCustomizer就會生效(定制錯誤的響應(yīng)規(guī)則);就會來到/error請求;就會被BasicErrorController處理;如果決定產(chǎn)生html數(shù)據(jù),而不是直接返回JSON數(shù)據(jù),就使用DefaultErrorViewResolver試圖解析器來解析我們的ModelAndView,最終決定返回哪個html文件。我們可以使用4xx和5xx作為錯誤頁面的文件名來匹配這種類型的所有錯誤,精確優(yōu)先(優(yōu)先尋找精確的狀態(tài)碼.html,比如發(fā)生404錯誤,有404.html就不去4xx.html了);我們將這些錯誤響應(yīng)的.html文件放到靜態(tài)資源路徑下的/error文件夾下即可。

通過上面的描述如果需要返回自己的錯誤返回界面,直接在靜態(tài)資源文件夾下新建/error文件夾,將自己的錯誤響應(yīng).html文件放到里面即可,這些.html文件可能是4xx.html、404.html、5xx.html、500.html。具體響應(yīng)哪個.html文件根據(jù)錯誤代碼來決定。如果需要自定義錯誤響應(yīng)信息,那么你還需要像下面這樣做:

1、只響應(yīng)JSON數(shù)據(jù),而不管請求的是什么(比如請求.html頁面,也返回JSON數(shù)據(jù))

首先新建@ControllerAdvice類,而后在其中寫@ExceptionHandler方法即可,如下:

@ControllerAdvice public class MyExceptionHandler {@ResponseBody@ExceptionHandler(UserNotExistException.class)public Map<String,Object> handleException(Exception e){Map<String,Object> map = new HashMap<>();map.put("code","user.notexist");map.put("message",e.getMessage());return map;} }

關(guān)于@ControllerAdvice注解更加詳細(xì)的解釋你可以看這里,在本文章中主要是結(jié)合@ExceptionHandler注解來處理錯誤。另外UserNotExistException是我們自定義的一個錯誤,由Controller拋出。

2、自適應(yīng)響應(yīng)

上面處理的方式有一個問題,就是不管是頁面請求,還是JSON數(shù)據(jù)請求,我們都是返回JSON數(shù)據(jù),如何做到請求JSON數(shù)據(jù)就返回JSON數(shù)據(jù),請求頁面就返回頁面呢?我們可以回到上面說到的BasicErrorController組件,這個組件會自適應(yīng)的處理/error請求,所以我們可以轉(zhuǎn)發(fā)到/error界面,如下所示:

@ControllerAdvice public class MyExceptionHandler {@ExceptionHandler(UserNotExistException.class)public String handleException(Exception e, HttpServletRequest request){//傳入我們自己的錯誤狀態(tài)碼 4xx 5xx,否則就不會進(jìn)入定制錯誤頁面的解析流程request.setAttribute("javax.servlet.error.status_code",500);//轉(zhuǎn)發(fā)到/errorreturn "forward:/error";} }

但是,這個時候我們又無法響應(yīng)我們自己定制的錯誤響應(yīng)數(shù)據(jù)了,我們希望不但可以自適應(yīng),又可以攜帶我們自定義的數(shù)據(jù)。如果你足夠細(xì)心的話,可以發(fā)現(xiàn),在上面BasicErrorController組件中,不論是響應(yīng)HTML頁面還是反回JSON數(shù)據(jù),都會調(diào)用getErrorAttributes這個方法,來設(shè)置錯誤響應(yīng)數(shù)據(jù),這個方法來自容器中的DefaultErrorAttributes組件,這個組件會在我們沒有在容器中添加ErrorAttributes組件的前提下添加到容器中作為默認(rèn)的ErrorAttributes以返回錯誤響應(yīng)數(shù)據(jù);所以我們?nèi)绻憫?yīng)我們自己的數(shù)據(jù),我們就要寫一個ErrorAttributes,并且實現(xiàn)它的getErrorAttributes方法,然后加入到容器中,為了簡單起見我們直接,繼承DefaultErrorAttributes然后重寫getErrorAttributes方法即可:

//給容器中加入我們自己定義的ErrorAttributes @Component public class MyErrorAttributes extends DefaultErrorAttributes {@Overridepublic Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,boolean includeStackTrace) {//保留默認(rèn)的錯誤處理數(shù)據(jù)Map<String, Object> map = super.getErrorAttributes(requestAttributes,includeStackTrace);//由具體的錯誤處理器填入的數(shù)據(jù),第二個參數(shù)的意思是scope,也就是從哪個域中獲取,0:request,1:session, .....map.put("ext", RequestAttributes.getAttribute("ext", 0));//所有錯誤都會填入的錯誤響應(yīng)數(shù)據(jù)map.put("company","BaiDu");return map;} }

上面注釋中說到的 “由具體的錯誤處理器填入的數(shù)據(jù)” 的意思是如下:

@ControllerAdvice public class MyExceptionHandler {@ExceptionHandler(UserNotExistException.class)public String handleException(Exception e, HttpServletRequest request){//傳入我們自己的錯誤狀態(tài)碼 4xx 5xx,否則就不會進(jìn)入定制錯誤頁面的解析流程request.setAttribute("javax.servlet.error.status_code",500);//填入額外的錯誤響應(yīng)處理數(shù)據(jù):Map<String,Object> map = new HashMap<>();map.put("code","user.notexist");map.put("message",e.getMessage());request.setAttribute("ext", map);//轉(zhuǎn)發(fā)到/errorreturn "forward:/error";} }

這樣一來我們就不但可以自適應(yīng)響應(yīng)數(shù)據(jù),還可以定制自己的錯誤響應(yīng)信息了。

總結(jié):
上面詳細(xì)講述了Spring Boot中發(fā)生錯誤后,如何處理的的流程,并且自定義錯誤響應(yīng)數(shù)據(jù)和界面。讀者可以選擇自己需要的功能來選擇如何處理,主要是懂得原理,這些處理方式就能使用的游刃有余。簡單分為以下兩點:

  • 不需要自定義錯誤響應(yīng)數(shù)據(jù),只要到我們自己的錯誤響應(yīng)界面,則編寫錯誤代碼對應(yīng)的HTML文件,并將這些錯誤響應(yīng)的.html文件放到靜態(tài)資源路徑下的/error文件夾下即可。
  • 需要自定義錯誤響應(yīng)數(shù)據(jù),并且自適應(yīng)響應(yīng),則在容器中加入我們自己的ErrorAttributes組件即可。

總結(jié)

以上是生活随笔為你收集整理的Spring Boot错误处理机制以及定制自己的错误页面的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。