aop 幂等验证

Posted 正怒月神

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了aop 幂等验证相关的知识,希望对你有一定的参考价值。

无法找到公用架包中,aop注解

 先看一下模块:

一,公用架包(com.common.aop)

定义注解:

package com.common.aop;

import java.lang.annotation.*;

/**
 * @description :
 * @auther Tyler
 * @date 2021/8/30
 */

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

注解实现

package com.common.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * @description :
 * @auther Tyler
 * @date 2021/8/30
 */

@Component
@Aspect
public class IdempotentAction {

    @Autowired
    HttpServletRequest request;
    public final static String ERROR_REPEATSUBMIT = "Repeated submission";

    //redis
    @Autowired
    protected StringRedisTemplate idempotentTemplate;

    @Pointcut("@annotation(com.tenyears.aop.IIdempotent)")
    private void controllerAspect() {
    }

    @Before("controllerAspect()")
    public void BeforeReturning(JoinPoint jp) throws Exception {
        IdempotentCheck(jp);
    }

    private void IdempotentCheck(JoinPoint jp) throws Exception {
//controller 名
        String controllerName = jp.getTarget().getClass().getName();
        Signature sig = jp.getSignature();
//方法名
        MethodSignature msig = (MethodSignature) sig;
        String method = msig.getMethod().getName();
//参数
        String body = NetUtil.getBodyString(request);
        //md5(Controller + method + body);
//md5 验证
        String signMD5= MD5.md5(controllerName+method+body);
        System.out.println("signMD5 :"+signMD5);
//存入redis 10秒过期
        if (Boolean.parseBoolean(idempotentTemplate.opsForValue().get(signMD5))) {
            throw new RuntimeException(ERROR_REPEATSUBMIT);
        } else {
            idempotentTemplate.opsForValue().set(signMD5, "true", 10, TimeUnit.SECONDS);
        }

    }
}


// netUtil.getBodyString方法
public static String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

二,项目中使用架包

application启动类

(重点,需要扫描架包,不然无法使用到!)

@SpringBootApplication
//必须要扫描到aop
@ComponentScan(basePackages={"com.common.aop"},lazyInit=true)
public class WebADApp {
    public static void main( String[] args )
    {
        SpringApplication.run(WebADApp.class, args);

    }
}

使用

@IIdempotent
    @RequestMapping(value = "test7", method = RequestMethod.POST)
    public void test7(ApiResult<String> req) {

        System.out.println(req.getData());
    }

以上是关于aop 幂等验证的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud项目如何防止重复提交,防重复提交幂等校验,Redis+aop+自定义Annotation实现接口

JAVA之AOP

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

Rails 在幂等种子文件中查找或创建 - 不通过验证

分布式接口的幂等性设计

SpringAOP01 利用AOP实现权限验证利用权限验证服务实现权限验证