需求:小程序登录时,后台需要将异常抛出,并将错误信息交给前台。
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; } }
if (student.getWechat() != null && !student.getWechat().getOpenid().equals(openId)) { throw new WechatLoginException("该学号已被其他微信帐号绑定,请联系老师或者管理员解除绑定", HttpStatus.valueOf(509)); }
// 处理微信登录的异常 @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()); }
后来,潘老师和张喜硕学长评论说这样写不好,因为 开放异常信息
,异常的状态码只靠注释约束,当返回未知状态码前台不知道如何处理。
根据潘老师的建议,做出如下修改:
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; } }
public class WechatLoginException extends RuntimeException { private int code; // 异常状态码 public WechatLoginException(HttpStatusEnum httpStatusEnum) { super(httpStatusEnum.getDescription()); code = httpStatusEnum.getCode(); } public int getCode() { return code; } }
throw new WechatLoginException(HttpStatusEnum.StudentISBinded);
//处理微信登录的异常 @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; } }
最后的效果:
总得来说,这次收获还是挺多的,遇到了不少问题,也对一些知识的盲区进行了探索和挖掘。虽然实现了需求,但觉得 小程序的异常处理还是有些生硬
,还有改进的余地。