Springboot通用异常处理

为什么要用通用异常处理

在日常的学习或者开发中难免会出现一些不可预知的异常需要我们去处理,并且也要有一定的响应,如果我们针对于每个异常都进行单独处理的话,那代码的简洁性和高可用性就不是很高。因此我们就应该使用一个通用的异常处理,并将它分离出来,可以对任何一个自定义异常进行有效的,规范的处理。

应该怎样去写通用异常处理

  1. 写一个自己的异常类,然后以后抛出异常的话就抛出自定义的异常,并在异常里面用枚举来封装异常信息。(一定要继承一个异常类)
package com.leyou.common.exception;

import com.leyou.common.enums.ExceptionEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
/*
*
* 比如简单的在controller使用如下
*    throw new LyException(ExceptionEnum.PRICE_CANNOT_NULL);
* */

@NoArgsConstructor
@AllArgsConstructor
@Getter
public class LyException extends RuntimeException {

    private ExceptionEnum exceptionEnum;

}

2.编写枚举类

package com.leyou.common.enums;


import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
/*
* 给枚举类提供构造方法,和get方法,枚举中构造函数默认都是私有的
* */
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum ExceptionEnum {


    PRICE_CANNOT_NULL(400,"价格不能为空"),
    CATEGORY_NOT_FOUND(404,"商品未找到"),
    ;
    
    private Integer code;
    private String msg;

}

  1. 编写异常处理结果类,为什么要编写异常处理结果类,往下看就知道了。
package com.leyou.common.vo;

import com.leyou.common.enums.ExceptionEnum;

public class ExceptionResult {
    private Integer status;
    private String message;
    private Long timestamp;

    public ExceptionResult(ExceptionEnum e){
        this.status = e.getCode();
        this.message = e.getMsg();
        this.timestamp = System.currentTimeMillis();
    }
}

4.编写通知处理

在没有结果处理类的处理方法,只能返回给前台一个字符串,这很明显不符合我们在springmvc中使用的restful风格,并且这样处理很不友好,也很单调

   //原始的,很麻烦而且很不通用,并且不能显示一个友好的错误信息!
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity handleException(RuntimeException e) {

//        就是处理BAD-REQUEST返回给前台的异常信息,message就是runtimeException里的参数字符串如下
//        throw new RuntimeException("不能查询到");
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
    }

在使用了结果处理类的情况下,可以很好的解决这一问题,并且让异常在前台的输出也十分规范,直接返回Exception对象,里面规范的封装着信息。

package com.leyou.common.advice;

import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.vo.ExceptionResult;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/*
 * 默认拦截加了所有controller的类,将common打包依赖放在service下即可调用
 * */
@ControllerAdvice
public class CommonExceptionHandler {

    //改进后的异常处理
    @ExceptionHandler(LyException.class)
    public ResponseEntity handleException(LyException e) {
        return ResponseEntity.status(e.getExceptionEnum().getCode())
                .body(new ExceptionResult(e.getExceptionEnum()));
    }

5.在实例中使用

package com.leyou.item.service;

import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.item.mapper.CategoryMapper;
import com.leyou.item.pojo.Category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;

@Service
public class CategoryService {

    @Autowired
    private CategoryMapper mapper;

    public List quaryListById(Long pid) {
        Category category = new Category();
        category.setParentId(pid);
        List list = mapper.select(category);
        //使用一个util中的判空,里包含有判空的所有条件
        if (CollectionUtils.isEmpty(list)){
            //抛出自定义异常404
            throw new LyException(ExceptionEnum.CATEGORY_NOT_FOUND);
        }
        return list;
    }
}

这样就很规范的解决了restful风格的异常处理!

你可能感兴趣的:(SpringBoot)