原理
@ControllerAdvice
+ @ExceptionHandler
统一处理应用级别的异常ErrorController
处理容器级别的异常,例如:404异常NoHandlerFoundException
异常处理404异常package com.github.mouday.common;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* 统一返回格式
*/
public class JsonResult implements Serializable {
private String msg;
private Integer code;
private Object data;
private JsonResult(Object data, String msg, Integer code) {
this.data = data;
this.msg = msg;
this.code = code;
}
public static JsonResult success(Object data) {
return new JsonResult(data, "success", 0);
}
public static JsonResult error() {
return new JsonResult(null, "error", -1);
}
public static JsonResult error(String msg) {
return new JsonResult(null, msg, -1);
}
public static JsonResult error(String msg, Integer code) {
return new JsonResult(null, msg, code);
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<>();
map.put("msg", this.msg);
map.put("code", this.code);
map.put("data", this.data);
return map;
}
}
package com.github.mouday.common;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 统一异常处理
* 参考
* https://www.jianshu.com/p/3998ea8b53a8
*/
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public JsonResult exceptionHandler(Throwable error) {
return JsonResult.error(error.getMessage(), -1);
}
}
ErrorController
处理404异常package com.github.mouday.controller;
import com.github.mouday.common.JsonResult;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* 处理404异常
*
* 参考
* https://www.cnblogs.com/54chensongxia/archive/2020/11/20/14007696.html
* https://blog.csdn.net/qq_38571892/article/details/123395165
*/
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
public class CustomErrorController extends BasicErrorController {
public CustomErrorController() {
super(new DefaultErrorAttributes(), new ErrorProperties());
}
/**
* 覆盖默认的JSON响应
*/
@Override
@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));
String message = (String) body.get("error");
Map<String, Object> result = JsonResult.error(message).toMap();
return new ResponseEntity<>(result, status);
}
}
现在,所有接口的返回格式就统一了
{
"msg": "服务端运行时异常",
"code": -1,
"data": null
}
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理404异常
* @param error
* @return
*/
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseBody
public JsonResult noHandlerFoundExceptionHandler(NoHandlerFoundException error) {
return JsonResult.error(error.getMessage(), -1);
}
}
application.yml 需要如下配置
spring:
mvc:
throw-exception-if-no-handler-found: true
web:
resources:
add-mappings: false
完整代码:https://github.com/mouday/spring-boot-demo
参考
Spring Boot优雅地处理404异常
SpringBoot 统一异常处理(附核心工具类-ErrorInfoBuilder)
Spring Boot之异常处理