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实现接口