需求:小程序登录时,后台需要将异常抛出,并将错误信息交给前台。
一、后台异常处理
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 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 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;
}
}
最后的效果:
总结
总得来说,这次收获还是挺多的,遇到了不少问题,也对一些知识的盲区进行了探索和挖掘。虽然实现了需求,但觉得小程序的异常处理还是有些生硬
,还有改进的余地。