··定义切面实现类
@Aspect
@Component
@Slf4j
public class LimitAccessTimesAspect {
@Autowired
private RedisTemplate redisTemplate;
@Before('@annotation(customannotationdemo.customannotationdemo.annotation.LimitAccessTimes)')
public void repeatSumbitIntercept(JoinPoint joinPoint) throws Exception{
// userTicket + 类名 + 方法 + timeout
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Cookie[] cookieList = request.getCookies();
String userTicket = null;
for (Cookie cookie : cookieList) {
if (cookie.getName().equals('userTicket')) {
userTicket = cookie.getValue();
break;
}
}
//获取当前切面所设置的方法的类名、方法名
String className = joinPoint.getTarget().getClass().getName();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
String methodName = method.getName();
// 获取配置的过期时间
LimitAccessTimes annotation = method.getAnnotation(LimitAccessTimes.class);
long timeout = annotation.timeout();
String key = userTicket + ':' + className + ':' + methodName + ':' + timeout + 's';
log.info(' --- >> 防重提交:key -- {}', key);
// 判断是否已经超过重复提交的限制时间
String value = redisTemplate.opsForValue().get(key);
if (StringUtils.isNotBlank(value)) { //如果不为空,说明redis设置的禁止访问时间未过期,抛出异常,禁止访问
String messge = MessageFormat.format('请勿在{0}s内重复提交', timeout);
throw new Exception(messge);
}
redisTemplate.opsForValue().set(key, key, timeout);
}
}
需要的pom依赖:
。
实现:
在段代码,流程是在执行接口方法前,获取用户的userTicker和访问的类和方法,将这几个参数拼接组成一个字符串,然后查询redis,如果没有结果,说明是第一次访问,把这个字符串写入redis,设置过期时间;之后在为过期的时候在访问,抛出异常,后续可以定义一个全局异常捕获,把异常信息抛出给前端
有一些场景,例如申请提交之后几秒内需要防止用户重复提交,我们后端通过自定义注解实现这一功能
新建一个自定义注解,定义变量
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LimitAccessTimes {
/**
* 指定时间内不可重复提交,单位:s
*
* @return
*/
long timeout() default 3;
}
在编写项目之前,如果要用自定义注解实现这一功能,需要导入springaop,redis依赖等
org.springframework.boot
spring-boot-starter-aop
test
org.aspectj
aspectjweaver
commons-lang
commons-lang
2.6
org.springframework.boot
spring-boot-starter-data-redis
文章为作者独立观点,不代表股票交易接口观点