SpringMVC Controllrt 层的异常处理 (@ExceptionHandler)

SpringMVC Controllrt 层的异常处理 :

 一、统一的返回格式

  当我向前端返回数据时,无论是否成功,我都希望能提供一个统一的返回格式,和一个友善的错误提示。所以在完成异常处理前,先提供一个统一的返回格式CommonReturnType,它暂时含有两个字段

  status 表示上传数据成功或者失败,data  则是要 上传的数据。当成功上传数据时,status 为 “success ”,data 为 数据;当失败时 status 为 “fail”, data 为 错误的详细。

    private String status;

    private Object data;

  代码:

package com.snapshot2.demo.response;

/**
 * 通用的返回体,用于向前端返回一个通用的数据结构体
 */
public class CommonReturnType {
    //表明返回的类型是"success " 或者 "fail"
    private String status;
    //若status = success data内放回前端需要的数据
    //若status = fail data内返回相应的错误信息
    private Object data;

    /* 两种创建方法 */
    /**
     * 当只传入数据data 时,默认成功
     * @param result
     * @return
     */
    public static CommonReturnType creat(Object result){
        return creat(result,"success");
    }

    /**
     * 当传入status 和 object 时使用这个创建方法
     * @param result
     * @param status
     * @return
     */
    public static CommonReturnType creat(Object result, String status){
        CommonReturnType commonReturnType = new CommonReturnType();
        commonReturnType.setData(result);
        commonReturnType.setStatus(status);
        return commonReturnType;
    }

    /* 省略 Getter and Setter */

  二、使用装饰器模式来自定义一个Controller 层的异常

    我们使用一个枚举来定义自己的一些异常类型,然后使用装饰器模式来实现对应的功能:

    UML 类设计图:

    

    代码实现:

   CommonErr:

 

package com.snapshot2.demo.error;

/**
 * 通用的异常接口,整合后端异常反馈给前端,使用装饰器模式
 * 这是装饰器的统一接口
 */
public interface CommonError {
    public int getErrCode();
    public String getErrMsg();
    public CommonError setErrMsg(String errMsg);
}

 

  CommonErrEnum:

package com.snapshot2.demo.error;

public enum CommonErrEnum implements CommonError {

    //00001 通用的参数不合法错误码
    PARAMTER_VALIDATION_ERROR(00001,"参数不合法"),
    UNKOWN_ERROR(00002,"未知错误"),
    //10000开头的错误码代表用户信息相关的错误
    USER_NOT_EXIST(100001,"用户不存在");

    private int errCode;
    private String errMsg;
    /* Constructor */

    CommonErrEnum(int errCode, String errMsg) {
        this.errCode = errCode;
        this.errMsg = errMsg;
    }

    @Override
    public int getErrCode() {
        return this.errCode;
    }

    @Override
    public String getErrMsg() {
        return this.errMsg;
    }

    @Override
    public CommonError setErrMsg(String errMsg) {
        this.errMsg = errMsg;
        return this;
    }
}

  UserExceprion

package com.snapshot2.demo.error;

/**
 * 使用到了包装器模式
 */
public class UserException extends Exception implements CommonError {

    //强关联一个CommonError(CommonErrorEnum)
    private CommonError commonError;

    //直接接受一个CommonEnum,用于构造一个业务异常
    public UserException(CommonError commonError){
        //调用Exception的初始化机制
        super();
        this.commonError = commonError;
    }

    /* Constructor */
    public UserException(CommonError commonError,String errMsg){
        super();
        this.commonError = commonError;
        this.commonError.setErrMsg(errMsg);
    }

    public void setCommonError(CommonError commonError) {
        this.commonError = commonError;
    }


    @Override
    public int getErrCode() {
        return this.commonError.getErrCode();
    }

    @Override
    public String getErrMsg() {
        return this.commonError.getErrMsg();
    }

    @Override
    public CommonError setErrMsg(String errMsg) {
        this.commonError.setErrMsg(errMsg);
        return this.commonError;
    }
}

  我们可以看到,UserException 继承与Exception类,又实现了CommonErr接口。它关联了一个实现CommonErr接口的类(这里就是我们定义的Enum类),并且可以使用并增强它的方法。

  之后我们就可以在Controller层使用@ExceptionHandler(Exception.class) 注解来捕获在Controler层出现的Exception异常,并且消化它,向前端返回友善的错误提示:

    //定义ExceptionHandler解决Controller层未被处理掉的异常
    @ExceptionHandler(Exception.class)
    //Controller 层返回的异常应该属于后端的异常
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Object handlerException(HttpServletRequest request, Exception e){
        Map<String,Object> responseData = new HashMap<>();
        CommonReturnType commonReturnType = new CommonReturnType();
        if(e instanceof UserException){
            //强制转化捕获的错误为UserException
            UserException userException = (UserException)e;
            //将错误信息转化为通用的上传格式
            commonReturnType.setStatus("fail");
            //将自定义的Exception 信息提取出来放在返回体中
            responseData.put("errCode",userException.getErrCode());
            responseData.put("errMsg",userException.getErrMsg());
            commonReturnType.setData(responseData);
        } else{
            responseData.put("errCode",CommonErrEnum.UNKOWN_ERROR.getErrCode());
            responseData.put("errMsg",CommonErrEnum.UNKOWN_ERROR.getErrMsg());
            commonReturnType.setStatus("fail");
            commonReturnType.setData(responseData);
        }
        return commonReturnType;

    }

 

posted @ 2018-12-27 20:55  Weeeeew  阅读(979)  评论(0编辑  收藏  举报