提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、@RestControllerAdvice
@RestControllerAdvice是Spring框架提供的一个注解,用于定义全局异常处理器和全局数据绑定设置。它结合了@ControllerAdvice和@ResponseBody两个注解的功能。
通过在@RestControllerAdvice类中定义异常处理方法,我们可以捕获和处理控制器中抛出的异常,提供自定义的异常处理逻辑,以及返回适当的响应给客户端。
二、案例
1.自定义异常
package com.easyblog.exception;
import com.easyblog.entity.enums.ResponseCodeEnum;
public class BusinessException extends RuntimeException {
private ResponseCodeEnum codeEnum;
private Integer code;
private String message;
public BusinessException(String message, Throwable e) {
super(message, e);
this.message = message;
}
public BusinessException(String message) {
super(message);
this.message = message;
}
public BusinessException(Throwable e) {
super(e);
}
public BusinessException(ResponseCodeEnum codeEnum) {
super(codeEnum.getMsg());
this.codeEnum = codeEnum;
this.code = codeEnum.getCode();
this.message = codeEnum.getMsg();
}
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
this.message = message;
}
public ResponseCodeEnum getCodeEnum() {
return codeEnum;
}
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
/**
* 重写fillInStackTrace 业务异常不需要堆栈信息,提高效率.
*/
@Override
public Throwable fillInStackTrace() {
return this;
}
}
2.自定义相应常量
package com.easyblog.entity.enums;
public enum ResponseCodeEnum {
CODE_200(200, "请求成功"),
CODE_404(404, "请求地址不存在"),
CODE_600(600, "请求参数错误"),
CODE_601(601, "信息已经存在"),
CODE_602(602, "信息提交过多"),
CODE_500(500, "服务器返回错误,请联系管理员"),
CODE_900(900, "http请求超时"),
CODE_901(901, "登录超时,请重新登录");
private Integer code;
private String msg;
ResponseCodeEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
3.自定义响应类
package com.easyblog.result;
import lombok.Data;
/**
* 全局统一返回结果类
*/
@Data
public class Result<T> {
private Integer code;
private String message;
private T data;
public Result(){}
protected static <T> Result<T> build(T data) {
Result<T> result = new Result<T>();
if (data != null)
result.setData(data);
return result;
}
public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
Result<T> result = build(body);
result.setCode(resultCodeEnum.getCode());
result.setMessage(resultCodeEnum.getMessage());
return result;
}
public static <T> Result<T> build(Integer code, String message) {
Result<T> result = build(null);
result.setCode(code);
result.setMessage(message);
return result;
}
public static<T> Result<T> ok(){
return Result.ok(null);
}
/**
* 操作成功
* @param data
* @param <T>
* @return
*/
public static<T> Result<T> ok(T data){
Result<T> result = build(data);
return build(data, ResultCodeEnum.SUCCESS);
}
public static<T> Result<T> fail(){
return Result.fail(null);
}
/**
* 操作失败
* @param data
* @param <T>
* @return
*/
public static<T> Result<T> fail(T data){
Result<T> result = build(data);
return build(data, ResultCodeEnum.FAIL);
}
public Result<T> message(String msg){
this.setMessage(msg);
return this;
}
public Result<T> code(Integer code){
this.setCode(code);
return this;
}
public boolean isOk() {
if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
return true;
}
return false;
}
}
4.核心逻辑
package com.easyblog.exception;
import com.easyblog.entity.enums.ResponseCodeEnum;
import com.easyblog.result.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
/**
* 全局异常捕获
* 可以捕获和处理控制器中抛出的异常,提供自定义的异常处理逻辑,以及返回适当的响应给客户端。
* **/
@RestControllerAdvice
public class GlobalExceptionHandlerController {
@ExceptionHandler(value = Exception.class)
Object handleException(Exception e, HttpServletRequest request) {
Result response=new Result<>();
//404
if (e instanceof NoHandlerFoundException) {
response.setCode(ResponseCodeEnum.CODE_404.getCode());
response.setMessage(ResponseCodeEnum.CODE_404.getMsg());
} else if (e instanceof BusinessException) {
//业务错误
BusinessException biz = (BusinessException) e;
response.setCode(biz.getCode());
if (biz.getCode() == null) {
response.setCode(ResponseCodeEnum.CODE_600.getCode());
}
response.setMessage(biz.getMessage());
} else if (e instanceof BindException) {
//参数类型错误
response.setCode(ResponseCodeEnum.CODE_600.getCode());
response.setMessage(ResponseCodeEnum.CODE_600.getMsg());
} else if (e instanceof DuplicateKeyException) {
//主键冲突
response.setCode(ResponseCodeEnum.CODE_601.getCode());
response.setMessage(ResponseCodeEnum.CODE_601.getMsg());
} else {
response.setCode(ResponseCodeEnum.CODE_500.getCode());
response.setMessage(ResponseCodeEnum.CODE_500.getMsg());
}
return response;
}
}
其中@ExceptionHandler:用于指定异常处理方法。当与@RestControllerAdvice配合使用时,用于全局处理控制器里的异常。
5.测试