返回的信息包含了异常下面 5 部分内容:
唯一标示异常的 code
HTTP状态码
错误路径
发生错误的时间戳
错误的具体信息
全局异常处理类
ErrorCode.java (此枚举类中包含了异常的唯一标识、HTTP状态码以及错误信息)
public enum ErrorCode {
RESOURCE_NOT_FOUND(1001, HttpStatus.NOT_FOUND, "未找到该资源"),
REQUEST_VALIDATION_FAILED(1002, HttpStatus.BAD_REQUEST, "请求数据格式验证失败");
private final int code;
private final HttpStatus status;
private final String message;
ErrorCode(int code, HttpStatus status, String message) {
this.code = code;
this.status = status;
this.message = message;
}
public int getCode() {
return code;
}
public HttpStatus getStatus() {
return status;
}
public String getMessage() {
return message;
}
@Override
public String toString() {
return "ErrorCode{" +
"code=" + code +
", status=" + status +
", message='" + message + '\'' +
'}';
}
}
BaseException.java(继承自 RuntimeException 的抽象类,可以看做系统中其他异常类的父类)
public class BaseException extends RuntimeException {
private final ErrorCode error;
private final HashMap<String, Object> data = new HashMap<>();
public BaseException(ErrorCode error, Map<String, Object> data) {
//super();
super(error.getMessage());
this.error = error;
if (!ObjectUtils.isEmpty(data)) {
this.data.putAll(data);
}
}
protected BaseException(ErrorCode error, Map<String, Object> data, Throwable cause) {
super(error.getMessage(), cause);
this.error = error;
if (!ObjectUtils.isEmpty(data)) {
this.data.putAll(data);
}
}
public ErrorCode getError() {
return error;
}
public Map<String, Object> getData() {
return data;
}
}
ErrorReponse.java(返回给客户端具体的异常对象)
@Data
public class ErrorReponse {
private int code;
private int status;
private String message;
private String path;
private Instant timestamp;
private HashMap<String, Object> data = new HashMap<String, Object>();
public ErrorReponse() {
}
public ErrorReponse(BaseException ex, String path) {
this(ex.getError().getCode(), ex.getError().getStatus().value(), ex.getError().getMessage(), path, ex.getData());
}
public ErrorReponse(int code, int status, String message, String path, Map<String, Object> data) {
this.code = code;
this.status = status;
this.message = message;
this.path = path;
this.timestamp = Instant.now();
if (!ObjectUtils.isEmpty(data)) {
this.data.putAll(data);
}
}
}
ResourceNotFoundException.java (自定义异常)
可以看出通过继承 BaseException 类我们自定义异常会变的
public class ResourceNotFoundException extends BaseException {
public ResourceNotFoundException(Map<String, Object> data) {
super(ErrorCode.RESOURCE_NOT_FOUND, data);
}
}
GlobalExceptionHandler.java(全局异常捕获)
@ControllerAdvice(assignableTypes = {ExceptionController.class})
@ResponseBody
public class GlobalExceptionHandler {
// 也可以将 BaseException 换为 RuntimeException
// 因为 RuntimeException 是 BaseException 的父类
@ExceptionHandler(BaseException.class)
public ResponseEntity<?> handleAppException(BaseException ex, HttpServletRequest request) {
ErrorReponse representation = new ErrorReponse(ex, request.getRequestURI());
return new ResponseEntity<>(representation, new HttpHeaders(), ex.getError().getStatus());
}
}
测试类
Person.java
@Data
@AllArgsConstructor
public class Person {
private Long id;
private String name;
}
ExceptionController.java(抛出异常的类)
@RestController
@RequestMapping("/api")
public class ExceptionController {
@GetMapping("/resourceNotFound")
public void throwException() {
Person p=new Person(1L,"SnailClimb");
HashMap<String, Object> map = new HashMap<>();
map.put("person id", 1);
//throw new ResourceNotFoundException(map);
throw new BaseException(REQUEST_VALIDATION_FAILED,map);
}
}
结果: