概述
个人学习用-搬运原文链接
1、需求
前后端分离项目中,后端通常是以json形式将数据返回给前端。此时,如果服务器内部出现异常,如何对内部异常处理后响应给前端呢?
2、实现方式
结合 @RestControllerAdvice 和 @ExceptionHandler 来捕获绝大部分异常,然后通过自定义的全局数据返回对象统一返回Json形式给前端。
@RestControllerAdvice: 增强类;
@ExceptionHandler: 标注异常处理方法,包括异常类型。
3、具体步骤
3.1、自定义 全局数据返回对象
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* 接口返回数据格式
*/
@Data
@ApiModel(value = "接口返回对象", description = "接口返回对象")
public class Result<T> implements Serializable {
/**
* 状态码
*/
private static final Integer HANDLE_OK = 200;
private static final Integer CLIENT_NOT_FOUND_404 = 404;
private static final Integer CLIENT_NO_AUTH_401 = 401;
private static final Integer SERVER_ERROR_500 = 500;
private static final Integer SERVER_NO_AUTH_510 = 200;
private static final long serialVersionUID = 1L;
/**
* 成功标志
*/
@ApiModelProperty(value = "成功标志")
private boolean success = true;
/**
* 返回处理消息
*/
@ApiModelProperty(value = "返回处理消息")
private String message = "";
/**
* 返回代码(状态码)
*/
@ApiModelProperty(value = "返回代码")
private Integer code = 0;
/**
* 返回数据对象 data
*/
@ApiModelProperty(value = "返回数据对象")
private T result;
/**
* 时间戳
*/
@ApiModelProperty(value = "时间戳")
private long timestamp = System.currentTimeMillis();
public Result() {
}
/**
* 兼容VUE3版token失效不跳转登录页面
* @param code
* @param message
*/
public Result(Integer code, String message) {
this.code = code;
this.message = message;
}
public Result<T> success(String message) {
this.message = message;
this.code = HANDLE_OK;
this.success = true;
return this;
}
public static <T> Result<T> ok() {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(HANDLE_OK);
return r;
}
public static <T> Result<T> ok(String msg) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(HANDLE_OK);
r.setMessage(msg);
r.setResult((T) msg);
return r;
}
public static <T> Result<T> ok(T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(HANDLE_OK);
r.setResult(data);
return r;
}
public static <T> Result<T> ok(String msg, T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(HANDLE_OK);
r.setMessage(msg);
r.setResult(data);
return r;
}
public static <T> Result<T> error(String msg) {
return error(SERVER_ERROR_500, msg);
}
public static <T> Result<T> error(String msg, T data) {
Result<T> r = new Result<T>();
r.setSuccess(false);
r.setCode(SERVER_ERROR_500);
r.setMessage(msg);
r.setResult(data);
return r;
}
public static <T> Result<T> error(int code, String msg) {
Result<T> r = new Result<T>();
r.setCode(code);
r.setMessage(msg);
r.setSuccess(false);
return r;
}
public Result<T> error500(String message) {
this.message = message;
this.code = SERVER_ERROR_500;
this.success = false;
return this;
}
/**
* 无权限访问返回结果
*/
public static <T> Result<T> noauth(String msg) {
return error(SERVER_NO_AUTH_510, msg);
}
}
3.2、自定义 全局异常捕获处理类
1. 清楚具体异常类型时
在类上,通过 @RestControllerAdvice(annotations = Controller.class) 注解标注全局异常处理类,指定处理带有@Controller注解的类,也就是controller层的所有方法。
在方法上,通过 @ExceptionHandler({ArithmeticException.class}) 标注异常处理方法以及方法所处理的异常类型。
@Slf4j
@RestControllerAdvice
public class ExceptionsHandler {
@ExceptionHandler({ArithmeticException.class})
public Result<String> arithmeticException(ArithmeticException ex) {
log.error("除数不能为0:{} ", ex.getMessage(), ex);
return Result.error(400, "除数不能为0");
}
}
2. 不清楚具体异常类型时,直接捕获异常的公共类 Exception
@ControllerAdvice(annotations = Controller.class)
public class ExceptionAdvice {
private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);
@ExceptionHandler(Exception.class)
public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
// 打印异常日志
logger.error(e.getMessage());
StackTraceElement[] stackTrace = e.getStackTrace();
for (StackTraceElement element : stackTrace) {
logger.error(element.toString());
}
// 返回处理结果,要判断异常发生的请求是普通请求(返回页面),还是异步请求(返回json数据)
String xRequestedWith = request.getHeader("x-requested-with");
// 异步请求
if (xRequestedWith.equals("XMLHttpRequest")) {
response.setContentType("application/plain;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(CommunityUtil.getJSONString(1, "服务器发生异常!"));
} else {
response.sendRedirect(request.getContextPath() + "/error");
}
}
}
3.3、编写测试方法
编写测试方法(会出现异常的方法)
@RestController
@RequestMapping("/exception")
public class ExceptionTestController {
@GetMapping("/test")
public Result<Integer> testException(int num) {
int res = 23 / num;
return Result.ok(res);
}
}
3.4、测试
异步请求: 返回json数据
普通方法: 返回页面
最后
以上就是懦弱纸飞机为你收集整理的SpringBoot 全局异常拦截捕获处理1、需求2、实现方式3、具体步骤的全部内容,希望文章能够帮你解决SpringBoot 全局异常拦截捕获处理1、需求2、实现方式3、具体步骤所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复