SpringBoot 项目 统一异常处理 + 用例

前言:统一异常处理类(切面类,如下 RequestAspect )返回的值,将会通过切入点(也就是这里那些被增强的接口方法)的返回类型返回。
也就是说,异常处理类假如返回类型是 Object ,那么接口的返回类型就必须大于等于 Object 类,才可以接得住异常处理类得返回值。
其实,关于 AOP 特性,有一个很重要的事情,切入面的返回数据最终还是要通过切入点的返回类型进行返回。
由此可得,统一异常类、接口类得返回类型统统写为 Object ,其实是一种规范。(当然有更好的规范)

统一异常处理使用 Spring AOP 机制,使用 Around 增强 Controller 类的每一个方法,即:对应每一个 SpringMVC 的 Mapping ,都对应的进行了统一的异常处理。
下面代码同时在其中嵌入了打印日志、统一返回数据类型(所有返回的对象都会被包装为统一数据类型)。

处理逻辑

  1. 获取时间、获取 request 、response、获取参数、获取请求 url;
  2. 切入点正常执行 -> 打印 url、时间、参数,返回统一返回类包装的数据;
  3. 切入点执行异常 -> 打印 url、时间、参数、异常信息,返回统一返回类包装的异常信息;

ps:注意这里是 controller 中返回 Object 类型数据的接口才会被接管,如需接管所有返回类型的接口,可用 * 代替 Object。

@Order(0)
@Slf4j
@Aspect
@Component
public class RequestAspect {
	private static final String LOGPATTERN = "请求发起:[%s][%s]%s";

    /**
     * 统一异常处理
     * @param joinPoint
     * @return
     */
    @Around("execution(public Object com.southgis.imap..controller..*.*(..))")
    public Object twiceAsOld(ProceedingJoinPoint joinPoint){
        // 开始时间,结束时间
        Long start = System.currentTimeMillis();
        Long end = System.currentTimeMillis();
        String paramStr = "";
        // request
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        // response
        HttpServletResponse response = ((ServletRequestAttributes)requestAttributes).getResponse();
        String uri = request.getRequestURI();
        try {
            // 获取参数
            Enumeration<String> enumeration = request.getParameterNames();
            Map<String,String> parameterMap = Maps.newHashMap();
            while (enumeration.hasMoreElements()){
                String parameter = enumeration.nextElement();
                parameterMap.put(parameter,request.getParameter(parameter));
            }
            paramStr = JSONObject.toJSONString(parameterMap);
            Object proceed = joinPoint.proceed();
            end = System.currentTimeMillis();
            if (log.isInfoEnabled()) {
            	log.info(String.format(LOGPATTERN, uri, (end-start), paramStr));
			}
            return formatResult(proceed, response);
        } catch (ServiceException e) {
        	if (e.getSource() != null) {
            	log.error(String.format(LOGPATTERN, uri, (end-start), paramStr), e.getSource());
			} else {
				log.error(e.getMessage());
			}

            if (e.getCode() == 400) {
                return AjaxRes.warnning(e.getMessage());
            }

            return AjaxRes.failMsg(e.getMessage());

        } catch (Throwable e) { //NOSONAR 此处本来就是设计成捕获所有异常,sonar 不应该检测此处的 Throwable
        	log.error(String.format(LOGPATTERN, uri, (end-start), paramStr), e);
            return AjaxRes.failMsg("服务器异常了:" + e.getMessage());
        }
    }

    // 格式化特定的数据结构
    private Object formatResult(Object result, HttpServletResponse response){
        if (result instanceof  AjaxRes) {
            return result;
        } else {
            return AjaxRes.success(result);
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值