spring-boot 自定义异常

需求:小程序登陆时,后台须要将异常抛出,并将错误信息交给前台。spring

1、后台异常处理

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());
}

存在的问题

后来,潘老师和张喜硕学长评论说这样写很差,由于开放异常信息,异常的状态码只靠注释约束,当返回未知状态码前台不知道如何处理。小程序

2、改进

根据潘老师的建议,作出以下修改:微信

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,如图:
clipboard.pngspring-boot

而张喜硕学长指出,spring-boot的HttpStatus枚举是不可扩展的,即我没法经过继承来增长自定义的http状态码
clipboard.png测试

因此,此时陷入一个僵局,要么放弃使用自定义状态码,要么放弃使用ResponseEntity,这时,张喜硕学长说了一下他的解决方案,即不返回ResponseEntity了,而是注入HttpServletResponse,调取setStatus()直接改返回的状态码:this

// 处理微信登陆的异常
@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();
}

而后在小程序端测试,发现果真状态码能够变成了自定义的了
clipboard.png
接着,就是在小程序端添加异常处理:url

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;
    }
 }

最后的效果:spa

clipboard.png

总结

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

相关文章
相关标签/搜索