统一异常处理
2020-09-21 本文已影响0人
乙腾
Overview
利用Spring AOP思想,对项目中的异常进行统一处理。
实现思路
通过@ControllerAdvice注解给控制器增加通知,接收所有Controller层的通知,再结合@ExceptionHandler解,对指定异常进行捕获。
code
BusinessExceptionHandler
package com.pl.daily.collection.component.exception;
import com.pl.daily.collection.component.response.ResponseResult;
import javafx.beans.binding.ObjectExpression;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* <p>
*
* @Description: TODO
* </p>
* @ClassName BusinessExceptionHandler
* @Author pl
* @Date 2020/9/20
* @Version V1.0.0
*/
@Slf4j
@ControllerAdvice
public class BusinessExceptionHandler {
@ExceptionHandler({BusinessException.class})
@ResponseBody//返回json格式数据
public ResponseResult<?> handlerException( BusinessException ex) {
ErrorCodeEnume errorCodeEnume = ex.getErrorCodeEnume();
log.info("[全局业务异常]\r\n业务编码:{}\r\n异常记录:{}",errorCodeEnume.getCode(), errorCodeEnume.getMsg());
return new ResponseResult<>(errorCodeEnume.getCode(),errorCodeEnume.getMsg());
}
@ExceptionHandler({Exception.class})
@ResponseBody
public ResponseResult<?> handlerException(Exception ex) {
log.info("[全局业务异常]\r\n业务编码:{}\r\n异常记录:{} \r\n 错误详情",ErrorCodeEnume.UNKNOW_EXCEPTION.getCode(), ErrorCodeEnume.UNKNOW_EXCEPTION.getMsg(),ex.getMessage());
return new ResponseResult<>(ErrorCodeEnume.UNKNOW_EXCEPTION.getCode(), ErrorCodeEnume.UNKNOW_EXCEPTION.getMsg(),ex.getMessage());
}
@ExceptionHandler({ArithmeticException.class})
@ResponseBody
public ResponseResult<?> handlerArithmeticException(Exception ex) {
log.info("[算术运算异常]\r\n业务编码:{}\r\n异常记录:{} \r\n 错误详情",ErrorCodeEnume.ARITHMETIC_EXCEPTION.getCode(), ErrorCodeEnume.ARITHMETIC_EXCEPTION.getMsg(),ex.getMessage());
return new ResponseResult<>(ErrorCodeEnume.UNKNOW_EXCEPTION.getCode(), ErrorCodeEnume.ARITHMETIC_EXCEPTION.getMsg(),ex.getMessage());
}
}
BusinessException自定义异常
package com.pl.daily.collection.component.exception;
/**
* <p>
*
* @Description: TODO
* </p>
* @ClassName BusinessException
* @Author pl
* @Date 2020/9/20
* @Version V1.0.0
*/
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = 4868842805385777275L;
private ErrorCodeEnume errorCodeEnume;
public BusinessException(ErrorCodeEnume errorCodeEnume) {
this.errorCodeEnume = errorCodeEnume;
}
public ErrorCodeEnume getErrorCodeEnume() {
return errorCodeEnume;
}
public void setErrorCodeEnume(ErrorCodeEnume errorCodeEnume) {
this.errorCodeEnume = errorCodeEnume;
}
}
ErrorCodeEnume
package com.pl.daily.collection.component.exception;
import java.util.Arrays;
/**
* @Auther: pl
* @Date: 2020/9/20 21:48
* @Description: 此枚举作为常量使用,为防止属性被修改,枚举中属性必须私有且不可改变,不能提供set方法
*/
public enum ErrorCodeEnume {
/**
* 系统未知异常
*/
UNKNOW_EXCEPTION(10000,"系统未知异常"),
/**
* 参数格式校验失败
*/
VAILD_EXCEPTION(10001,"参数格式校验失败"),
/**
* 成功
*/
SUCCESS(200,"参数格式校验失败"),
/**
* 算术运算异
*/
ARITHMETIC_EXCEPTION(10100,"算术运算异常"),
;
//错误码
private final int code;
//错误信息
private final String msg;
/**
* 根据Key得到枚举的实例
* Lambda表达式,比较判断(JDK 1.8)
*
* @param key
* @return
*/
public static ErrorCodeEnume getEnumType3(int key) {
return Arrays.asList(ErrorCodeEnume.values()).stream()
.filter(errorCodeEnume -> errorCodeEnume.code == key)
.findFirst().orElse(ErrorCodeEnume.UNKNOW_EXCEPTION);
}
ErrorCodeEnume(int code,String msg){
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
service层
import com.pl.common.exception.BizCodeEnume;
import com.pl.common.exception.BusinessException;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pl.common.utils.PageUtils;
import com.pl.common.utils.Query;
import com.pl.gulimail.order.dao.OrderDao;
import com.pl.gulimail.order.entity.OrderEntity;
import com.pl.gulimail.order.service.OrderService;
@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
@Override
public int testException(String xx) {
if (StringUtils.isEmpty(xx)){
//直接抛出异常
throw new BusinessException(BizCodeEnume.VAILD_EXCEPTION);
}
return 0;
}
}
异常抛给controller
controller层正常写
import java.util.Arrays;
import java.util.Map;
import com.pl.common.exception.BizCodeEnume;
import com.pl.common.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.pl.gulimail.order.entity.OrderEntity;
import com.pl.gulimail.order.service.OrderService;
import com.pl.common.utils.PageUtils;
import com.pl.common.utils.R;
/**
* 订单
*
* @author pl
* @email 158040608010@163.com
* @date 2020-07-03 18:21:34
*/
@RestController
@RequestMapping("order/order")
public class OrderController {
/**
* 列表
*/
@RequestMapping("/test")
public R test(){
orderService.testException(null);
return R.ok();
}
}
144757359.png
notice:
1.@ExceptionHandler 可以按照实际需要捕获指定的一些异常,使异常更加准确
2.实际使用统一异常处理,可能会改变一些代码习惯,如:
- 减少很多业务判断
- 节省一部分trycatch代码块(对于需要特殊处理的异常还是不能省略的,如io流等)
- 统一异常可以让一些方法减少非必要的返回,直接用void修饰,减少返回值,这要可以对内存优化提供正面帮助,减少返回值,也就是减少局部变量表,减少栈帧的大小,增加栈内方法的调用次数,为栈节省空间