JAVA执行异常增加重试方案

前言

在程序查询接口时,有时执行中会出现错误,包括一些未知错误,这些错误本身是软件本身的错误,比如数据库的底层错误,我们无法解决这些错误,这时会因为这些原因导致请求失败,此时我们希望能够自动重试该请求,以提高系统的可靠性和稳定性。

解决方案

在AOP切面中@Around环绕通知方法增加重试机制

@Aspect
@Component
public class WebLogAspect {

    private final static Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    private static final String BAD_SQL_GRAMMAR_EXCEPTION = "org.springframework.jdbc.BadSqlGrammarException";
    private static final String UNKNOWN_ERROR = "Unknown error";

    @Pointcut("execution(public * xxx.xxx.xxx.xxx.controller..*.*(..))")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 打印请求相关参数
        logger.info("{\"Request_Detail\":{" +
                        "\"URL\":\"{}\"," +
                        "\"HTTP_Method\":\"{}\"," +
                        "\"Class_Method\":\"{}.{}\"," +
                        "\"IP\":\"{}\"" +
                        "}}",
                request.getRequestURL().toString(),
                request.getMethod(),
                joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(),
                request.getRemoteAddr()
        );
        // 打印请求入参
        logger.info("{\"Request_Args\":{}}", JSON.toJSON(joinPoint.getArgs()));
    }

    @Around("pointcut()")
    public Object Around(ProceedingJoinPoint point) throws Throwable {
        int maxRetryNum = 3;//重试最大次数
        int nowRetryNum = 0;//当前重试次数
        Throwable lastException;//记录最后异常
        do {
            nowRetryNum++;
            try {
                Object proceed = point.proceed();//切点方法
                // 打印出参
                logger.info("{\"Response_Args\":{}}", JSON.toJSON(proceed));
                return proceed;
            } catch (Throwable e) {
                lastException = e;
                String exceptionName = e.getClass().getName();//获取异常类名
                String detailMessage = e.getCause() == null ? e.getMessage() : e.getCause().getMessage();//获取异常具体消息
                //判断是否为SR查询异常
                if (!BAD_SQL_GRAMMAR_EXCEPTION.equals(exceptionName) || StringUtils.isEmpty(detailMessage) || !detailMessage.contains(UNKNOWN_ERROR)) {
                    //停止请求重试
                    nowRetryNum = maxRetryNum + 1;
                } else {
                    //重试日志打印
                    logger.warn("{\"Request_Retry\"{}\"\":{" +
                                    "\"Exception_Name\":\"{}\"," +
                                    "\"Exception_Message\":\"{}\"" +
                                    "}}",
                            nowRetryNum,
                            e.getClass().getName(),
                            e.getMessage()
                    );
                }
            }
        } while (nowRetryNum <= maxRetryNum);
        throw lastException;
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值