springboot統(tǒng)一異常處理(返回json)并格式化異常
統(tǒng)一異常處理
當(dāng)用spring boot開(kāi)發(fā)后端時(shí),我們常采用前后端分離的開(kāi)發(fā)策略,這時(shí)候要求前端與后端需要進(jìn)行數(shù)據(jù)交互,傳統(tǒng)的一般采用json數(shù)據(jù)交互。
這時(shí)候我們要對(duì)spring boot的默認(rèn)異常處理方式進(jìn)行修改了,要統(tǒng)一返回?cái)?shù)據(jù)格式,優(yōu)雅的數(shù)據(jù)交互,優(yōu)雅的開(kāi)發(fā)應(yīng)用。
首先我們要了解一般springboot的錯(cuò)誤發(fā)生在什么地方。
一般發(fā)生在controller、業(yè)務(wù)層、filter中(如spring security)、攔截器中、還有就是未知錯(cuò)誤了。
下面我分享一下我的處理方式: @RestControllerAdvice+filter+重寫(xiě)B(tài)asicErrorController的處理方式。
@RestControllerAdvice
@RestControllerAdvice+@ExceptionHandler(Exception.class)可以處理經(jīng)過(guò)controller的異常錯(cuò)誤
@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("當(dāng)前頁(yè)面不存在");
}
}filter捕獲所有異常
當(dāng)錯(cuò)誤沒(méi)有經(jīng)過(guò)controller時(shí),@RestControllerAdvice是不能捕獲的,這時(shí)候就需要在filter進(jìn)行處理。
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一定要注冊(cè)到springboot才有作用,下面是我喜歡的一種方式
@Bean
FilterRegistrationBean<ExceptionHandlerFilter> exceptionFilterRegistrationBean() {
FilterRegistrationBean<ExceptionHandlerFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new ExceptionHandlerFilter());
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);//放在最前面
return bean;
}未知異常處理
當(dāng)發(fā)生的異常不知道在哪時(shí),springboot會(huì)進(jìn)行默認(rèn)異常處理,跳轉(zhuǎn)到 /error
這時(shí)我們要統(tǒng)一數(shù)據(jù)返回就必須要從這下手了,創(chuàng)建一個(gè)新的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));
//可以換成項(xiàng)目中自定義的通信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é)果返回的工具類(lèi)
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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot的控制反轉(zhuǎn)和自動(dòng)裝配示例代碼
這篇文章主要介紹了springboot的控制反轉(zhuǎn)和自動(dòng)裝配的相關(guān)知識(shí),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
Ajax實(shí)現(xiàn)省市區(qū)三級(jí)聯(lián)動(dòng)
這篇文章主要為大家詳細(xì)介紹了jQuery ajax實(shí)現(xiàn)省市縣三級(jí)聯(lián)動(dòng)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能幫助到你2021-07-07
Spring?Boot項(xiàng)目啟動(dòng)報(bào)錯(cuò)Unable?to?start?web?server解決方法
這篇文章主要給大家介紹了關(guān)于Spring?Boot項(xiàng)目啟動(dòng)報(bào)錯(cuò)Unable?to?start?web?server的解決方法,錯(cuò)誤內(nèi)容大概的意思是未能加載嵌入的供web應(yīng)用加載的空間,是因?yàn)槿鄙賁ervletWebServerFactorybean,需要的朋友可以參考下2024-07-07
詳解SpringBoot定制@ResponseBody注解返回的Json格式
這篇文章主要介紹了詳解SpringBoot定制@ResponseBody注解返回的Json格式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
SpringBoot詳細(xì)講解靜態(tài)資源導(dǎo)入的實(shí)現(xiàn)
在Web開(kāi)發(fā)過(guò)程中,我們需要接觸許多靜態(tài)資源,如CSS、JS、圖片等;在之前的開(kāi)發(fā)中,這些資源都放在Web目錄下,用到的時(shí)候按照對(duì)應(yīng)路徑訪(fǎng)問(wèn)即可。不過(guò)在SpringBoot項(xiàng)目中,沒(méi)有了Web目錄,那這些靜態(tài)資源該放到哪里去,又要如何訪(fǎng)問(wèn)呢?這就是我們要講的靜態(tài)資源導(dǎo)入2022-05-05
SpringBoot2零基礎(chǔ)到精通之異常處理與web原生組件注入
SpringBoot是Spring全家桶的成員之一,基于約定優(yōu)于配置的思想(即有約定默認(rèn)值,在不配置的情況下會(huì)使用默認(rèn)值,在配置文件下配置的話(huà)會(huì)使用配置的值)。SpringBoot是一種整合Spring技術(shù)棧的方式(或者說(shuō)是框架),同時(shí)也是簡(jiǎn)化Spring的一種快速開(kāi)發(fā)的腳手架2022-03-03

