javascript
springboot获取静态图片路径_SpringBoot中的全局异常处理你确定你真的知道吗?
本篇要點
- 介紹SpringBoot默認的異常處理機制。
- 如何定義錯誤頁面。
- 如何自定義異常數據。
- 如何自定義視圖解析。
- 介紹@ControllerAdvice注解處理異常。
一、SpringBoot默認的異常處理機制
默認情況下,SpringBoot為以下兩種情況提供了不同的響應方式:
SpringBoot默認提供了程序出錯的結果映射路徑/error,這個請求的處理邏輯在BasicErrorController中處理,處理邏輯如下:
// 判斷mediaType類型是否為text/html @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {HttpStatus status = getStatus(request);Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML)));response.setStatus(status.value());// 創建ModelAndView對象,返回頁面ModelAndView modelAndView = resolveErrorView(request, response, status, model);return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); }@RequestMapping public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {HttpStatus status = getStatus(request);if (status == HttpStatus.NO_CONTENT) {return new ResponseEntity<>(status);}Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));return new ResponseEntity<>(body, status); }二、錯誤頁面的定制
相信Whitelabel Error Pag頁面我們經常會遇到,這樣體驗不是很好,在SpringBoot中可以嘗試定制錯誤頁面,定制方式主要分靜態和動態兩種:
在classpath:/public/error或classpath:/static/error路徑下定義相關頁面:文件名應為確切的狀態代碼,如404.html,或系列掩碼,如4xx.html。
舉個例子,如果你想匹配404或5開頭的所有狀態代碼到靜態的html文件,你的文件目錄應該是下面這個樣子:
src/+- main/+- java/| + <source code>+- resources/+- public/+- error/| +- 404.html| +- 5xx.html+- <other public assets>如果500.html和5xx.html同時生效,那么優先展示500.html頁面。
放置在classpath:/templates/error路徑下:這里使用thymeleaf模板舉例:
src/+- main/+- java/| + <source code>+- resources/+- templates/+- error/| +- 5xx.html+- <other templates>頁面如下:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>5xx</title></head><body><h1>5xx</h1><p th:text="'error -->'+ ${error}"></p><p th:text="'status -->' + ${status}"></p><p th:text="'timestamp -->' + ${timestamp}"></p><p th:text="'message -->' + ${message}"></p><p th:text="'path -->' +${path}"></p><p th:text="'trace -->' + ${trace}"></p></body> </html>如果靜態頁面和動態頁面同時存在且都能匹配,SpringBoot對于錯誤頁面的優先展示規則如下: 如果發生了500錯誤: 動態500 -> 靜態500 -> 動態5xx -> 靜態5xx三、自定義異常數據
默認的數據主要是以下幾個,這些數據定義在org.springframework.boot.web.servlet.error.DefaultErrorAttributes中,數據的定義在getErrorAttributes方法中。
DefaultErrorAttributes類在org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration自動配置類中定義:
@Bean@ConditionalOnMissingBean(value = ErrorAttributes.class,search = SearchStrategy.CURRENT)public DefaultErrorAttributes errorAttributes() {return new DefaultErrorAttributes();}如果我們沒有提供ErrorAttributes的實例,SpringBoot默認提供一個DefaultErrorAttributes實例。
因此,我們就該知道如何去自定義異常數據屬性:
定義方式如下:
/*** 自定義異常數據* @author Summerday*/ @Slf4j @Component public class MyErrorAttributes extends DefaultErrorAttributes {@Overridepublic Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {Map<String, Object> map = super.getErrorAttributes(webRequest, options);if(map.get("status").equals(500)){log.warn("服務器內部異常");}return map;} }四、自定義異常視圖
自定義視圖的加載邏輯存在于BasicErrorController類的errorHtml方法中,用于返回一個ModelAndView對象,這個方法中,首先通過getErrorAttributes獲取到異常數據,然后調用resolveErrorView去創建一個ModelAndView對象,只有創建失敗的時候,用戶才會看到默認的錯誤提示頁面。
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {HttpStatus status = getStatus(request);Map<String, Object> model = Collections.unmodifiableMap(//ErrorAttributes # getErrorAttributesgetErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML)));response.setStatus(status.value());// EModelAndView modelAndView = resolveErrorView(request, response, status, model);return (modelAndView != null) ? modelAndView : new ModelAndView("error", model); }DefaultErrorViewResolver類的resolveErrorView方法:
@Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {// 以異常狀態碼作為視圖名去locations路徑中去查找頁面ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);// 如果找不到,以4xx,5xx series去查找if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);}return modelAndView; }那么如何自定義呢?和自定義異常數據相同,如果我們定義了一個ErrorViewResolver的實例,默認的配置就會失效。
/*** 自定義異常視圖解析* @author Summerday*/@Component public class MyErrorViewResolver extends DefaultErrorViewResolver {public MyErrorViewResolver(ApplicationContext applicationContext, ResourceProperties resourceProperties) {super(applicationContext, resourceProperties);}@Overridepublic ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {return new ModelAndView("/hyh/resolve",model);} }此時,SpringBoot將會去/hyh目錄下尋找resolve.html頁面。
五、@ControllerAdvice注解處理異常
前后端分離的年代,后端往往需要向前端返回統一格式的json信息,以下為封裝的AjaxResult對象:
public class AjaxResult extends HashMap<String, Object> {//狀態碼public static final String CODE_TAG = "code";//返回內容public static final String MSG_TAG = "msg";//數據對象public static final String DATA_TAG = "data";private static final long serialVersionUID = 1L;public AjaxResult() {}public AjaxResult(int code, String msg) {super.put(CODE_TAG, code);super.put(MSG_TAG, msg);}public AjaxResult(int code, String msg, Object data) {super.put(CODE_TAG, code);super.put(MSG_TAG, msg);if (data != null) {super.put(DATA_TAG, data);}}public static AjaxResult ok() {return AjaxResult.ok("操作成功");}public static AjaxResult ok(Object data) {return AjaxResult.ok("操作成功", data);}public static AjaxResult ok(String msg) {return AjaxResult.ok(msg, null);}public static AjaxResult ok(String msg, Object data) {return new AjaxResult(HttpStatus.OK.value(), msg, data);}public static AjaxResult error() {return AjaxResult.error("操作失敗");}public static AjaxResult error(String msg) {return AjaxResult.error(msg, null);}public static AjaxResult error(String msg, Object data) {return new AjaxResult(HttpStatus.INTERNAL_SERVER_ERROR.value(), msg, data);}public static AjaxResult error(int code, String msg) {return new AjaxResult(code, msg, null);} }根據業務的需求不同,我們往往也需要自定義異常類,便于維護:
/*** 自定義異常** @author Summerday*/ public class CustomException extends RuntimeException {private static final long serialVersionUID = 1L;private Integer code;private final String message;public CustomException(String message) {this.message = message;}public CustomException(String message, Integer code) {this.message = message;this.code = code;}public CustomException(String message, Throwable e) {super(message, e);this.message = message;}@Overridepublic String getMessage() {return message;}public Integer getCode() {return code;} }@ControllerAdvice和@RestControllerAdvice這倆注解的功能之一,就是做到Controller層面的異常處理,而兩者的區別,與@Controller和@RestController差不多。
@ExceptionHandler指定需要處理的異常類,針對自定義異常,如果是ajax請求,返回json信息,如果是普通web請求,返回ModelAndView對象。
/*** 全局異常處理器* @author Summerday*/@RestControllerAdvice public class GlobalExceptionHandler {private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);@ExceptionHandler(CustomException.class)public Object handle(HttpServletRequest request, CustomException e) {AjaxResult info = AjaxResult.error(e.getMessage());log.error(e.getMessage());// 判斷是否為ajax請求if (isAjaxRequest(request)) {return info;}ModelAndView mv = new ModelAndView();mv.setViewName("custom"); // templates/custom.htmlmv.addAllObjects(info);mv.addObject("url", request.getRequestURL());return mv;}private boolean isAjaxRequest(HttpServletRequest request) {return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));} }在Controller層,人為定義拋出異常:
@RestController public class TestController {@GetMapping("/ajax")public AjaxResult ajax() {double alpha = 0.9;if (Math.random() < alpha) {throw new CustomException("自定義異常!");}return AjaxResult.ok();} }最后,通過/templates/custom.html定義的動態模板頁面展示數據:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>自定義界面</title></head><body><p th:text="'msg -->'+ ${msg}"></p><p th:text="'code -->'+ ${code}"></p><p th:text="'url -->'+ ${url}"></p></body> </html>源碼下載
總結
以上是生活随笔為你收集整理的springboot获取静态图片路径_SpringBoot中的全局异常处理你确定你真的知道吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为荣耀u8860刷机包
- 下一篇: 《蜡笔物理学》第七大关7-9