spring-boot 自定义异常

18次阅读

共计 3355 个字符,预计需要花费 9 分钟才能阅读完成。

需求:小程序登录时,后台需要将异常抛出,并将错误信息交给前台。
一、后台异常处理
1. 自定义微信登录异常
public class WechatLoginException extends RuntimeException {
/**
* @Description 自定义状态码
* 510:未找到该学号或该学号的状态已冻结
* 509:该学号已被其他微信帐号绑定,请联系老师或者管理员解除绑定
* 508:该微信帐号已绑定学号,请解除绑定后重新登录
**/
private HttpStatus status = null;
public WechatLoginException(String message, HttpStatus httpStatus) {
super(message);
status = httpStatus;
}

public HttpStatus getStatus() {
return status;
}
}
2.userService 抛出异常
if (student.getWechat() != null && !student.getWechat().getOpenid().equals(openId)) {
throw new WechatLoginException(“ 该学号已被其他微信帐号绑定,请联系老师或者管理员解除绑定 ”, HttpStatus.valueOf(509));
}
3. 全局异常处理
// 处理微信登录的异常
@ExceptionHandler(WechatLoginException.class)
public ResponseEntity<JsonErrorResult> wechatLoginHandler(HttpServletRequest request, WechatLoginException e){
logger.error(“ 微信登录异常:—Host {} invokes url {} ERROR: {}”, request.getRemoteHost(), request.getRequestURL(), e.getMessage());
return new ResponseEntity<>(new JsonErrorResult(request, e), e.getStatus());
}
存在的问题
后来,潘老师和张喜硕学长评论说这样写不好,因为开放异常信息,异常的状态码只靠注释约束,当返回未知状态码前台不知道如何处理。
二、改进
根据潘老师的建议,做出如下修改:
1. 添加异常状态枚举
public enum HttpStatusEnum {
StudentNotFound(“ 未找到该学生 ”, 601),
StudentIsForzen(“ 该学生的状态已冻结 ”, 602),
StudentISBinded(“ 该学号已被其他微信帐号绑定,请联系老师或者管理员解除绑定 ”, 603),
WecahtIsBinded(“ 该微信帐号已绑定学号,请解除绑定后重新登录 ”, 604);

private String description;
private int code;

private HttpStatusEnum (String description, int code) {
this.description = description;
this.code = code;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public int getCode() {
return code;
}

public void setCode(int code) {
this.code = code;
}
}
2. 异常类修改,构造时传入枚举体
public class WechatLoginException extends RuntimeException {
private int code; // 异常状态码
public WechatLoginException(HttpStatusEnum httpStatusEnum) {
super(httpStatusEnum.getDescription());
code = httpStatusEnum.getCode();
}

public int getCode() {
return code;
}
}
3. service 抛出异常
throw new WechatLoginException(HttpStatusEnum.StudentISBinded);
4. 全局异常处理
// 处理微信登录的异常
@ExceptionHandler(WechatLoginException.class)
public ResponseEntity<JsonErrorResult> wechatLoginHandler(HttpServletRequest request, WechatLoginException e){
logger.error(“ 微信登录异常:—Host {} invokes url {} ERROR: {}”, request.getRemoteHost(), request.getRequestURL(), e.getMessage());
return new ResponseEntity<>(new JsonErrorResult(request, e), e.getStatus());
}
然后这一步就出现了问题,使用 ResponseEntity 返回异常信息时,第二个参数需要传入 HttpStatus,如图:
而张喜硕学长指出,spring-boot 的 HttpStatus 枚举是不可扩展的,即我无法通过继承来增加自定义的 http 状态码
所以,此时陷入一个僵局,要么放弃使用自定义状态码,要么放弃使用 ResponseEntity,这时,张喜硕学长说了一下他的解决方案,即不返回 ResponseEntity 了,而是注入 HttpServletResponse,调取 setStatus() 直接改返回的状态码:
// 处理微信登录的异常
@ExceptionHandler(value = WechatLoginException.class)
public String WechatLoginExceptionHandler(HttpServletRequest request, HttpServletResponse response, WechatLoginException e) throws IOException {
logger.error(“ 微信登录异常:—Host {} invokes url {} ERROR: {}”, request.getRemoteHost(), request.getRequestURL(), e.getMessage());
response.setStatus(e.getCode());
return e.getMessage();
}
然后在小程序端测试,发现果然状态码可以变成了自定义的了接着,就是在小程序端添加异常处理:
public static handleHttpException(response: RequestSuccessCallbackResult) {
let result = ”;
switch (response.statusCode) {
case 601:
result = ‘ 未找到该学生 ’;
break;
case 602:
result = ‘ 该学生的状态已冻结 ’;
break;
case 603:
result = ‘ 该学号已被其他微信帐号绑定,请联系老师或者管理员解除绑定 ’;
break;
case 604:
result = ‘ 该微信帐号已绑定学号,请解除绑定后重新登录 ’;
}
// 如果异常信息不为空,则显示提示信息,并且抛出异常
if (result != ”) {
// 显示异常
wx.showToast({
title: result,
icon: “none”,
duration: Request.duration
});
throw response;
}
}
最后的效果:

总结
总得来说,这次收获还是挺多的,遇到了不少问题,也对一些知识的盲区进行了探索和挖掘。虽然实现了需求,但觉得小程序的异常处理还是有些生硬,还有改进的余地。

正文完
 0