Spring AOP 学习之注解解决重复提交,异常日志处理

1.AOP + Redis 解决重复提交

 重复提交是我们日常中比较频繁发生的事情,用户可以点击一个按钮多次,如未加相应的处理,就会请求后台多次,每次请求对后台服务来说都是一次性能的消耗,有些非幂等接口更是会有很多的业务问题,为此解决重复提交是一件非常重要的事情。当然解决重复提交也有很多种方法,如接口幂等,redis,数据库,mq等等,现讲解Spring + redis的方案解决重复提交,根据每次的请求路径+用户的请求sessionId来判别是否是同一个用户,通过判断用户请求的key是否在redis中存在来判别是否失效,话不多说,show me your code!

1.1 先写注解

/** * @version V1.0
 * @Description 防止重复提交
 * @date 2020/7/15 19:39.
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoRepeatSubmit {

    /**
     * 设置请求锁定时间
     *
     * @return
     */
    int lockTime() default 3;

}

1.2 注解防止重复提交

/** * @version V1.0
 * @Description 防止重复提交
 * @date 2020/7/15 19:46.
 */
@Slf4j
@Aspect
@Component
public class RepeatSubmitAspect {

    @Autowired
    private RedisTemplate<String, Integer> redisTemplate;

    @Pointcut("@annotation(noRepeatSubmit)")
    public void pointCut(NoRepeatSubmit noRepeatSubmit) {
    }

    @Around("pointCut(noRepeatSubmit)")
    public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) {
        ValueOperations<String, Integer> opsForValue = redisTemplate.opsForValue();
        try {
            int lockSeconds = noRepeatSubmit.lockTime();
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            String sessionId = RequestContextHolder.getRequestAttributes().getSessionId();
            HttpServletRequest request = attributes.getRequest();
            String key = sessionId + ":" + request.getServletPath();
            // 如果缓存中有这个url视为重复提交
            if (opsForValue.get(key) == null) {
                Object o = pjp.proceed();
                opsForValue.set(key, 0, lockSeconds, TimeUnit.SECONDS);
                return o;
            } else {
                log.info("重复提交");
                return RtnUtil.getFailMsgRtn("请勿重复提交~");
            }
        } catch (Throwable e) {
            e.printStackTrace();
            log.error("验证重复提交时出现未知异常!");
            return RtnUtil.getOkMsgRtn("验证重复提交时出现未知异常!");
        }
    }

}

1.3 接口加注解解决重复提交

    @NoRepeatSubmit(lockTime = 5)

 

2. AOP + DB 解决异常日志记录写库

2.1 先写注解

/** * @version V1.0
 * @Description 描述
 * @date 2020/7/21 12:52.
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OperateLog {
    /**
     * 业务名称
     * @return
     */
    String businessName() default "操作日志";
    /**
     * 业务类型
     * @return
     */
    String businessType() default "system";
}

2.2 切面处理异常记录入库

/** * @version V1.0
 * @Description 描述
 * @date 2020/7/21 12:53.
 */
@Aspect
@Component
public class OperateLogAspect {

    @Pointcut(value = "@annotation(operateLog) && args(obj)")
    public void pointCut(OperateLog operateLog, Object obj) {

    }

    @AfterThrowing(pointcut = "pointCut(operateLog,obj)", throwing = "ex")
    public void afterThrowing(OperateLog operateLog, BusinessException ex, Object obj) {
        if (operateLog.businessType().equalsIgnoreCase("operator:bussiness")) {
            ParamObj paramObj = (ParamObj) obj;
           System.out.println("save::" + paramObj.toString());
        }
    }

}

 

 

 

posted @ 2020-07-21 19:43  Antony_hubei  阅读(475)  评论(0编辑  收藏  举报