Springboot封装自定义响应与统一异常处理

1、封装自定义响应

在实际项目中,一般会把结果放在一个封装类中,封装类中包含http状态值,状态消息,以及实际的数据。

/**
 * Json格式的数据进行响应
 * 因为所有的响应的结果都采用Json格式的数据进行响应,所以需要实现Serializable接口
 */
@Data
public class JsonResult<E> implements Serializable {
    private Integer state;    // 状态码
    private String  message;  // 描述信息
    // 数据类型不确定,用E表示任何的数据类型,一个类里如果声明的有泛型的数据类型,类也要声明为泛型
    private E data;           // 数据
    //无参构造
    public JsonResult() {
    }
​
    //将状态码传给构造方法初始化对象
    public JsonResult(Integer state) {
        this.state = state;
    }
​
    //将状态码和数据传给构造方法初始化对象
    public JsonResult(Integer state, E data) {
        this.state = state;
        this.data = data;
    }
​
    //如果有异常,直接将异常传递给构造方法初始化对象
    public JsonResult(Throwable e) {
​
        this.message=e.getMessage();
    }
    /**以及属性的get和set方法*/
}

2、统一异常处理

如果访问到了不存在的页面,或者服务器内出现了异常,SpringBoot会返回默认的错误页面。可以将自定义的错误页面放到SpringBoot的默认规则下的路径。

生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。

2.1、Service层规划可能出现的异常

  • 创建业务层异常类的基类-ServiceException继承RuntimeException,重写五个异常处理方法。

  • 创建具体的异常处理类-每一个都要继承ServiceException,并重写方法。

    • UserNotFoundException--用户名不存在异常

    • UsernameDuplicatedException--用户名被占用异常

    • PasswordNotMatchException--密码校验不匹配异常

    • InsertException--插入异常

    • UpdateException--更新数据异常

    /**
     * 业务层异常的基类
     */
    public class ServiceException extends RuntimeException{
        // 什么也不返回
        public ServiceException() {
            super();
        }
        //返回异常信息(常用)
        public ServiceException(String message) {
            super(message);
        }
        //返回异常信息和异常对象(常用)
        public ServiceException(String message, Throwable cause) {
            super(message, cause);
        }
        public ServiceException(Throwable cause) {
            super(cause);
        }
        protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    }
  • 规划好异常后,需要在ServiceImpl写相应业务逻辑,碰到异常就处理。

    // 通过user参数来获取传递过来的username
            String username = user.getUsername();
            // 调用findByUsername(username)判断是否被注册过
            User result = userMapper.findByUsername(username);
            // 判断结果集是否为null,不为null的话则需抛出用户名被占用的异常
            if(result !=null){
                // 抛出异常
                throw new UsernameDuplicatedException("用户名被占用!");
            }

2.2、Controller层统一异常处理

  1. 创建控制层基类BaseController--使用@RestControllerAdvice+@ExceptionHandler表示该方法用于处理捕获抛出的异常

    @ControllerAdvice 注解的原理是SpringAOP提供的,是将Controller层的方法作为切面,从而对Controller层方法进行拦截处理。

/** 控制层类的基类*/
@RestControllerAdvice
public class BaseController {
    public static final int ok = 200;   // 操作成功的状态码
​
    /**
     * 1.@ExceptionHandler表示该方法用于处理捕获抛出的异常
     * 2.什么样的异常才会被这个方法处理呢?所以需要ServiceException.class,
     *   这样的话只要是抛出ServiceException异常就会被拦截到handleException方法,
     *   此时handleException方法就是请求处理方法,返回值就是需要传递给前端的数据
     * 3.被ExceptionHandler修饰后如果项目发生异常,那么异常对象就会被自动传递给此方法的参数列表上,
     *   所以形参就需要写Throwable e用来接收异常对象
     */
    @ExceptionHandler({ServiceException.class,FileUploadException.class})  // 用于统一处理抛出的异常
    public JsonResult<Void> handlerException(Throwable e){
        JsonResult<Void> result = new JsonResult<>();
        if(e instanceof UsernameDuplicatedException){
            result.setState(4000);
            result.setMessage("用户名已被占用");
        }else if(e instanceof UserNotFoundException){
            result.setState(5001);
            result.setMessage("用户名不存在的异常");
        }else if(e instanceof PasswordNotMatchException){
            result.setState(5002);
            result.setMessage("用户名密码错误的异常");
        }else if(e instanceof InsertException){
            result.setState(5003);
            result.setMessage("注册时产生未知的异常");
        }else if (e instanceof UpdateException) {
            result.setState(5004);
            result.setMessage("更新数据时产生未知的异常");
        }else if (e instanceof FileEmptyException) {
            result.setState(6000);
        } else if (e instanceof FileSizeException) {
            result.setState(6001);
        } else if (e instanceof FileTypeException) {
            result.setState(6002);
        } else if (e instanceof FileStateException) {
            result.setState(6003);
        } else if (e instanceof FileUploadIOException) {
            result.setState(6004);
        } else if (e instanceof AddressCountLimitException) {
            result.setState(4003);
            result.setMessage("用户的收货地址超出上限的异常");
        }
​
        return result;
    }
}
  1. 规划创建Controller层要处理的异常

    同service层,相同的方式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈水水水水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值