springboot統(tǒng)一異常處理(返回json)并格式化異常
統(tǒng)一異常處理
當用spring boot開發(fā)后端時,我們常采用前后端分離的開發(fā)策略,這時候要求前端與后端需要進行數(shù)據(jù)交互,傳統(tǒng)的一般采用json數(shù)據(jù)交互。
這時候我們要對spring boot的默認異常處理方式進行修改了,要統(tǒng)一返回數(shù)據(jù)格式,優(yōu)雅的數(shù)據(jù)交互,優(yōu)雅的開發(fā)應(yīng)用。
首先我們要了解一般springboot的錯誤發(fā)生在什么地方。
一般發(fā)生在controller、業(yè)務(wù)層、filter中(如spring security)、攔截器中、還有就是未知錯誤了。
下面我分享一下我的處理方式: @RestControllerAdvice+filter+重寫B(tài)asicErrorController的處理方式。
@RestControllerAdvice
@RestControllerAdvice+@ExceptionHandler(Exception.class)可以處理經(jīng)過controller的異常錯誤
@RestControllerAdvice public class BaseExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(BaseExceptionHandler.class); /** * 未知異常 * @param e 異常 * @return 統(tǒng)一結(jié)果返回 */ @ExceptionHandler(Exception.class) public R exception(Exception e) { logger.error(e.getMessage(), e); return R.error().message(e.getMessage()); } @ExceptionHandler(NoHandlerFoundException.class) public R noHandlerFoundException(){ return R.error().message("當前頁面不存在"); } }
filter捕獲所有異常
當錯誤沒有經(jīng)過controller時,@RestControllerAdvice是不能捕獲的,這時候就需要在filter進行處理。
public class ExceptionHandlerFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain){ try { filterChain.doFilter(servletRequest, servletResponse); } catch (Exception e) { ResponseUtils.out((HttpServletResponse) servletResponse, R.error().message(e.getMessage())); } } }
記得filter一定要注冊到springboot才有作用,下面是我喜歡的一種方式
@Bean FilterRegistrationBean<ExceptionHandlerFilter> exceptionFilterRegistrationBean() { FilterRegistrationBean<ExceptionHandlerFilter> bean = new FilterRegistrationBean<>(); bean.setFilter(new ExceptionHandlerFilter()); bean.setOrder(Ordered.HIGHEST_PRECEDENCE);//放在最前面 return bean; }
未知異常處理
當發(fā)生的異常不知道在哪時,springboot會進行默認異常處理,跳轉(zhuǎn)到 /error
這時我們要統(tǒng)一數(shù)據(jù)返回就必須要從這下手了,創(chuàng)建一個新的Controller處理/error,繼承BasicErrorController,并覆蓋其中的方法
@RestController public class MyErrorController extends BasicErrorController { @Autowired public MyErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties, List<ErrorViewResolver> errorViewResolvers) { super(errorAttributes, serverProperties.getError(), errorViewResolvers); } @Override public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML))); // return new ModelAndView("error", model, status); ResponseUtils.out(response, R.error().code(status.value()).message((String) model.get("error"))); return null; } @Override public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL)); //可以換成項目中自定義的通信json Map<String, Object> resultBody = new HashMap<>(16); resultBody.put("success", false); resultBody.put("code", body.get("status")); resultBody.put("message", body.get("error")); Map<String, Object> data = new HashMap<>(); data.put("timestamp", body.get("timestamp")); data.put("path", body.get("path")); resultBody.put("data", data); return new ResponseEntity<>(resultBody, HttpStatus.OK); } }
配置文件
spring: mvc: throw-exception-if-no-handler-found: true web: resources: add-mappings: false server: error: include-exception: true servlet: encoding: charset: utf-8
統(tǒng)一結(jié)果返回的工具類
ResponseUtils
public class ResponseUtils { public static void out(HttpServletResponse response, R r) { ObjectMapper mapper = new ObjectMapper(); response.setStatus(HttpStatus.OK.value()); response.setContentType("application/json;charset=UTF-8"); try { mapper.writeValue(response.getWriter(), r); } catch (IOException e) { e.printStackTrace(); } }
R
@Data public class R implements Serializable { private boolean success; private Integer code; private String message; private Map<String,Object> data; private R(){} public static R ok(){ R r = new R(); r.setSuccess(true); r.setCode(200); r.setMessage("成功"); r.setData(new HashMap<>()); return r; } public static R error() { R r = new R(); r.setSuccess(false); r.setCode(500); r.setMessage("失敗"); r.setData(new HashMap<>()); return r; } public R success(Boolean success){ this.success = success; return this; } public R code(Integer code){ this.code = code; return this; } public R message(String message){ this.message = message; return this; } public R data(String key, Object value){ this.data.put(key,value); return this; } public R data(Map<String,Object> map){ this.setData(map); return this; } }
到此這篇關(guān)于springboot統(tǒng)一異常處理(返回json)并格式化異常的文章就介紹到這了,更多相關(guān)springboot統(tǒng)一異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot的控制反轉(zhuǎn)和自動裝配示例代碼
這篇文章主要介紹了springboot的控制反轉(zhuǎn)和自動裝配的相關(guān)知識,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06Spring?Boot項目啟動報錯Unable?to?start?web?server解決方法
這篇文章主要給大家介紹了關(guān)于Spring?Boot項目啟動報錯Unable?to?start?web?server的解決方法,錯誤內(nèi)容大概的意思是未能加載嵌入的供web應(yīng)用加載的空間,是因為缺少ServletWebServerFactorybean,需要的朋友可以參考下2024-07-07詳解SpringBoot定制@ResponseBody注解返回的Json格式
這篇文章主要介紹了詳解SpringBoot定制@ResponseBody注解返回的Json格式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11SpringBoot詳細講解靜態(tài)資源導(dǎo)入的實現(xiàn)
在Web開發(fā)過程中,我們需要接觸許多靜態(tài)資源,如CSS、JS、圖片等;在之前的開發(fā)中,這些資源都放在Web目錄下,用到的時候按照對應(yīng)路徑訪問即可。不過在SpringBoot項目中,沒有了Web目錄,那這些靜態(tài)資源該放到哪里去,又要如何訪問呢?這就是我們要講的靜態(tài)資源導(dǎo)入2022-05-05SpringBoot2零基礎(chǔ)到精通之異常處理與web原生組件注入
SpringBoot是Spring全家桶的成員之一,基于約定優(yōu)于配置的思想(即有約定默認值,在不配置的情況下會使用默認值,在配置文件下配置的話會使用配置的值)。SpringBoot是一種整合Spring技術(shù)棧的方式(或者說是框架),同時也是簡化Spring的一種快速開發(fā)的腳手架2022-03-03