自定义注解实现前端防抖,重复调用接口,3秒内,一般前端抖动都在1秒内,这个不属于互联网说的接口防刷,就是单纯的防止前端因抖动连发2次请求,造成脏数据,比如我的代码中有推送微信公众号通知,连发2条一模一样的通知给用户,属实不友好。故而解决方案如下
1、导入依赖,直接填进去,当然他会选择你spring boot的版本
<!-- spring AOP --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency>
2、自定义注解
package com.component.common.web.annotation;
import java.lang.annotation.*;
/**
* 防止重复请求注解
*/
@Inherited
@Documented
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotRepeated {
}
3、配置缓存
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
/**
* 本地缓存用的是google guava cache,缓存有效期是3秒
*/
@Configuration
public class CacheConfig {
@Bean
public Cache repeatCache(){
final Cache<Object, String> repeatCache = CacheBuilder.newBuilder()
// cache的初始大小
.initialCapacity(20)
// 并发数
.concurrencyLevel(10)
// cache中的数据在写入之后的存活时间为3秒
.expireAfterWrite(3, TimeUnit.SECONDS)
.build();
return repeatCache;
}
}
4、写切面类
import com.google.common.cache.Cache;
import com.vzoom.hermes.component.common.exection.BaseCustomizeException;
import com.xiaoleilu.hutool.util.ArrayUtil;
import lombok.extern.slf4j.Slf4j;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
//@ComponentScan
//@EnableAspectJAutoProxy
public class NotRepeatedAspect {
/**
* 注入缓存
*/
@Autowired
private Cache<Object, Object> repeatCache;
/**
* 切入点
*/
@Pointcut("@annotation(com.component.common.web.annotation.NotRepeated)")
public void duplicate() {
}
/**
* 切面核心逻辑
* @param joinPoint 切入点
* @return 返回对象
* @throws Throwable 抛出异常的可能性
*/
@Around("duplicate()")
public Object repeatRequestCheck(ProceedingJoinPoint joinPoint) throws Throwable{
Object result;
/* Object[] args = joinPoint.getArgs();
if (ArrayUtil.isNotEmpty(args)){
Object key = args[0];
log.info("防重复请求缓存实时数量:{}", repeatCache.size());
if (repeatCache.getIfPresent(key) == null){
repeatCache.put(key, System.currentTimeMillis());
result = joinPoint.proceed();
} else{
// 抛出统一异常处理类
throw new BaseCustomizeException("0001","","前端抖动,重复请求本接口");
}
} else{
result = joinPoint.proceed();
}*/
// 优化
HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest();
String requestURI = request.getRequestURI();
//全局获取用户id与他的机构id
Object userId = request.getAttribute(CommonConstant.CURRENT_USER_ID);
Object tanentId = request.getAttribute(CommonConstant.CURRENT_TANENT_ID);
String key= userId +"::"+ tanentId +"::"+requestURI;
log.info(JSONUtil.toJsonStr(key));
log.info("防重复请求缓存实时数量:{}", repeatCache.size());
if (repeatCache.getIfPresent(key) == null){
repeatCache.put(key, System.currentTimeMillis());
result = joinPoint.proceed();
} else{
repeatCache.invalidate(key);
throw new BaseCustomizeException("0001","","前端抖动,重复请求本接口");
}
return result;
}
}
maven version报红
直接clean一下,再install一下;就行了。
分享一个坑,其实就是公司私服的jar有问题,同事的代码都跑的好好的,唯独我的报找不到类.....
实际上就是maven私服上的jar和同事本地仓库的jar有出入,私服的有问题。现在推荐一个插件来排查这样的问题。
Dependency Analyzer:settings-->pulgins-->Dependency Analyzer-->install-->restart;
下载之后安装就好了。
然后随便打开一个pom.xml就可以在文件左下角看到Dependency Analyzer,之后直接搜你需要的包名,就可以在右侧一栏中看到它的父级依赖包名,之后一级一级的向上找。
之后如果有报错,就是依赖jar没有引用到,用查一下之后就能知道改包是那个包引用进来的,之后找到改jar看看他的pom里面是否引用了