自定义统一异常处理

本文介绍了如何在SpringBoot项目中使用自定义注解`@ResponseException`捕获异常,并通过AspectJ实现全局异常处理,包括自定义异常类`AppClientException`和异常信息的封装、记录以及企业微信告警。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 自定义异常

package cn.com.app.client.annotation;

import java.lang.annotation.*;


@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseException {

}

2. 自定义异常使用

package cn.com.app.client.api;


import cn.com.app.base.constant.CommonConst;
import cn.com.app.base.enums.AppRespCodeEnum;
import cn.com.app.client.annotation.ResponseException;
import cn.com.app.client.exception.EppClientException;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Objects;


@Component
public class AppServiceImpl implements AppServiceApi {


    @ResponseException
    @Override
    public JSONObject executeApi(@RequestBody JSONObject reqJson) {
        
		log.info("请求参数:{}", reqJson);
        String mobile = reqJson.getString("mobile");
        
        if (StringUtils.isBlank(mobile)){
            throw new AppClientException(AppRespCodeEnum.ParamsVerify.ERROR_01001);
        }
        return reqJson;
    }

}

3. 自定义异常处理

package cn.com.app.client.aspect;

import cn.com.app.base.dto.SystemExceptionMsgDto;
import cn.com.app.base.enums.AppRespCodeEnum;
import cn.com.app.base.service.SystemExcepWxWarnService;
import cn.com.app.client.common.ClientMessageService;
import cn.com.app.client.exception.EppClientException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;


@Aspect
@Component
public class ResponseAspect {

    @Autowired
    private SystemExcepWxWarnService systemExcepWxWarnService;

    @Pointcut("@annotation(cn.com.sand.epp.client.annotation.ResponseException)")
    public void response() {

    }

    @Around("response()")
    public JSONObject interceptorResult(ProceedingJoinPoint proceedingJoinPoint) {
        log.error("=====[app-client]异常处理,系统异常");

        JSONObject responseJson = null;
        try {
            Object[] args = proceedingJoinPoint.getArgs();
            Object result = proceedingJoinPoint.proceed(args);
            responseJson = JSONObject.parseObject(JSONObject.toJSONString(result));
        } catch (Throwable e) {
            // 统一异常处理
            doException(proceedingJoinPoint, e);
        }
        return responseJson;
    }


    private JSONObject doException(ProceedingJoinPoint proceedingJoinPoint, Throwable err) {
        SystemExceptionMsgDto systemExceptionMsgDto = this.assemblySystemExceptionMsgDto(proceedingJoinPoint, err);
        // 发送企业微信告警
        systemExcepWxWarnService.sendWxMessage(systemExceptionMsgDto);
        String code = AppRespCodeEnum.ERROR_9999.getValue();
        String desc = AppRespCodeEnum.ERROR_9999.getDesc();
        if (err instanceof AppClientException) {
            AppClientException excp = (AppClientException) err;
            code = excp.getIEnum().getValue();
            if (StringUtils.isNotBlank(excp.getExtendDesc())){
                desc = excp.getExtendDesc();
            }else {
                desc = excp.getIEnum().getDesc();
            }
        }
        return Response.error(reqJson, code, desc);
    }

   

	private SystemExceptionMsgDto assemblySystemExceptionMsgDto(ProceedingJoinPoint joinPoint, Throwable err){
        SystemExceptionMsgDto systemExceptionMsgDto = SystemExceptionMsgDto.builder()
                .exceptionDesc(err.getMessage())
                .exception(err)
                .build();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        systemExceptionMsgDto.setRequestUrl(className + "." + methodName);
        Map<String, Object> methodParameters = new HashMap<>();
        //获取方法请求参数
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String[] paramNames = methodSignature.getParameterNames();
        Object[] paramValues = joinPoint.getArgs();
        if (paramNames != null && paramNames.length > 0) {
            for (int i = 0; i < paramNames.length; i++) {
                if(!(paramValues[i] instanceof Serializable)){
                    // 不支持序列化的数据,不进行序列化
                    continue;
                }
                BUSILOGGER.info("入参: "+paramNames[i] +" : "+paramValues[i]);
                methodParameters.put(paramNames[i], JSON.toJSONString(paramValues[i]));
            }
            systemExceptionMsgDto.setRequestParam(JSON.toJSONString(methodParameters));
        }

        return systemExceptionMsgDto;
    }
}

4. AppClientException

package cn.com.app.client.exception;

import cn.com.app.base.constant.emums.IEnum;
import cn.com.app.base.constant.utils.EnumUtil;
import cn.com.app.base.exception.utils.ExceptionUtil;
import org.apache.commons.lang3.StringUtils;


public class AppClientException extends RuntimeException {
	
	private IEnum iEnum;
    protected String extendDesc;
    	
	public AppClientException(String code, String desc, String extendDesc, Throwable cause) {
		super(desc, cause);
        this.iEnum = newIEnum(code, desc);
        this.extendException = new ExtendException();
        this.extendDesc = extendDesc;
    }
	
	public AppClientException(String code, String desc, String extendDesc) {
        this(code, desc, extendDesc, (Throwable)null);
    }

    public AppClientException(String code, String... desc) {
        this.extendException = new ExtendException();
        this.iEnum = EnumUtil.newIEnum(code, desc);
    }

}



public static IEnum newIEnum(String value, String... desc) {
        IEnum iEnum = new IEnum() {
            private String value;
            private String desc;

            public void setValue(String value, String desc) {
                this.value = value;
                this.desc = desc;
            }

            public String getValue() {
                return this.value;
            }

            public String getDesc() {
                return this.desc;
            }

            public String toString() {
                return "[" + this.value + "]" + this.desc;
            }
        };
        StringBuilder sb = new StringBuilder();

        for(int i = 0; i < desc.length; ++i) {
            sb.append(desc[i]);
        }

        iEnum.setValue(value, sb.toString());
        return iEnum;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值