主要是业务场景是为了防止一个接口被同一个用户频繁访问
以下是主要代码
package com.xmcbs.jjcommon.util;
import com.xmcbs.jjcommon.enums.PreventStrategy;
import java.lang.annotation.*;
/**
* @author :wangjp
* @date :2023/7/11 11:42
*/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Prevent {
/**
* 限制的时间值(秒)默认60s
*/
long value() default 5;
/**
* 限制规定时间内访问次数,默认只能访问一次
*/
long times() default 1;
/**
* 提示
*/
String message() default "";
}
以下是注解实现类
将访问存到redis并设置过期时间,如果存在说明在这个时间段重复访问,则将报错信息返回
package com.xmcbs.jjcommon.util;
import com.xmcbs.jeeplusboot.core.exception.BusinessException;
import com.xmcbs.jeeplusboot.core.exception.PlatformException;
import com.xmcbs.jeeplusboot.core.util.StringUtil;
import com.xmcbs.jeeplusboot.core.util.redis.RedisUtil;
import com.xmcbs.jeeplusboot.modules.base.service.PlatFormService;
import com.xmcbs.jeeplusboot.modules.system.entity.SystemUser;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
/**
* @author :wangjp
* @date :2023/7/11 14:45
*/
@Aspect
@Component
public class PreventAop {
@Resource
private RedisTemplate<String, Long> redisTemplate;
@Autowired
private PlatFormService platFormService;
/**
* 切入点
*/
@Pointcut("@annotation(com.xmcbs.jjcommon.util.Prevent)")
public void pointcut() {}
/**
* 处理前
*/
@Before("pointcut()")
public void joinPoint(JoinPoint joinPoint) throws Exception {
SystemUser systemUser = platFormService.getCurrentUser();
// 获取调用者ip
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
// String userIP = IpUtils.getUserIP(httpServletRequest);
// 获取调用接口方法名
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = joinPoint.getTarget().getClass().getMethod(
methodSignature.getName(),
methodSignature.getParameterTypes()); // 获取该接口方法
String methodFullName = method.getDeclaringClass().getName() + method.getName(); // 获取到方法名
Prevent preventAnnotation = method.getAnnotation(Prevent.class); // 获取该接口上的prevent注解(为了使用该注解内的参数)
String json = RedisUtil.get("Prevent:" + method.getName() + ":" + systemUser.getId());
if(StringUtil.isEmpty(json)){
System.out.println(preventAnnotation.times());
RedisUtil.set("Prevent:" + method.getName() + ":" + systemUser.getId(),systemUser.getId(),preventAnnotation.times());
}else{
throw new PlatformException(preventAnnotation.message());
}
}
}
使用:在调用接口上面加注解就行了
不加参数就是默认类里面的参数