jfinal 注解@interface,接口访问次数限制

在开发中,难免会遇到接口的访问次数限制等功能,比如防止狂刷,验证码的请求次数限制等。

下边博主使用jfinal + redis实现了这一个功能。

首先创建@interface类

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface RequestLimit {
    /**
     * 
     * 允许访问的次数,默认值MAX_VALUE
     */
    long count() default Integer.MAX_VALUE;
 
    /**
     * 
     * 时间段,单位为秒,默认值一分钟
     */
    int time() default 60;
}
然后创建拦截器 .
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.sunjs.utils.IpUtils;
 
/**
 * LimitInterceptor.
 */
public class LimitInterceptor implements Interceptor {
     
    public void intercept(Invocation inv) {
        RequestLimit limit = inv.getMethod().getAnnotation(RequestLimit.class);
        if (limit != null){
            long count = limit.count();
            int time = limit.time();
             
            String ip = IpUtils.getIpAddr(inv.getController().getRequest());
             
            String uri = inv.getController().getRequest().getRequestURI();
             
            /** 操作redis cache **/
            String cacheKey = "visit_limit_"+uri+"_"+ip;
            Cache cache = Redis.use(PropKit.get("redis.cachename"));
            Long visitNum = cache.incr(cacheKey);
            if(visitNum==1){
                //第一次访问需要在redis中增加过期时间
                cache.expire(cacheKey, time);
            }
            if (visitNum > count) {  
                inv.getController().renderJson("请求次数频繁,请稍后重试");
                return ;
            }  
        }
        inv.invoke();
    }
     
}

获取ip的工具类这里就不公布了,网上一搜一大堆。

具体如何限制访问次数,自己去扩展吧,比如返回页面,返回json,或者输入验证码才可以进行下一步....

记得在config启动加载中配置此拦截器

public void configInterceptor(Interceptors me) {
        me.add(new LimitInterceptor());
    }
配置redis插件:
public void configPlugin(Plugins me) {
         
        // 用于缓存博客模块的redis服务
        RedisPlugin newsRedis = new RedisPlugin(PropKit.get("redis.cachename"),
                PropKit.get("redis.host"), PropKit.getInt("redis.port"),
                PropKit.getInt("redis.timeout"), PropKit.get("redis.password"));
        me.add(newsRedis);
    }

然后在请求方法中就可以注解了,很简单的小例子。

@RequestLimit(count=60, time=60)  //60秒请求次数限制60次



更多详细讲解和文章请到个人博客查看


版权属于: 技术客

原文地址: https://www.sunjs.com/article/detail/04118233795a4c08af221d0ca32e2126.html

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。







可以使用Spring AOP(面向切面编程)来实现接口限制访问次数的功能。 首先,需要定义一个注解来标识需要限制访问次数接口,比如@AccessLimit: ```java @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AccessLimit { int seconds(); int maxCount(); } ``` 然后,在AOP切面中实现对该注解的解析和限制访问次数的功能: ```java @Aspect @Component public class AccessLimitAspect { private final RedisTemplate<String, Integer> redisTemplate; @Autowired public AccessLimitAspect(RedisTemplate<String, Integer> redisTemplate) { this.redisTemplate = redisTemplate; } @Around("@annotation(accessLimit)") public Object around(ProceedingJoinPoint point, AccessLimit accessLimit) throws Throwable { // 获取方法名和参数作为缓存的key MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); String methodName = method.getName(); Object[] args = point.getArgs(); String key = methodName + Arrays.toString(args); // 获取当前时间戳和过期时间戳 long currentTime = System.currentTimeMillis(); long expireTime = currentTime + accessLimit.seconds() * 1000; // 查询缓存中的访问次数 Integer count = redisTemplate.opsForValue().get(key); if (count == null) { // 缓存中没有该key,表示该接口第一次被访问,设置访问次数为1并设置过期时间 redisTemplate.opsForValue().set(key, 1, accessLimit.seconds(), TimeUnit.SECONDS); } else { if (count >= accessLimit.maxCount()) { // 访问次数超过限制,返回错误信息 throw new RuntimeException("访问次数超过限制"); } else { // 访问次数加1并更新过期时间 redisTemplate.opsForValue().increment(key, 1); redisTemplate.expire(key, expireTime - currentTime, TimeUnit.MILLISECONDS); } } // 执行目标方法 return point.proceed(); } } ``` 在这个切面中,我们使用了Redis作为缓存来存储接口访问次数和过期时间。在每次访问限制接口时,我们先根据方法名和参数作为缓存的key查询缓存中的访问次数,如果缓存中没有该key,则表示该接口第一次被访问,设置访问次数为1并设置过期时间。如果缓存中已经有该key,则判断访问次数是否超过限制,如果超过限制则返回错误信息,否则访问次数加1并更新过期时间。最后执行目标方法。 要使用该AOP切面,只需要在需要限制访问次数接口上添加@AccessLimit注解即可: ```java @RestController public class UserController { @AccessLimit(seconds = 60, maxCount = 5) @GetMapping("/user/info") public String getUserInfo(@RequestParam("id") Integer id) { // ... } } ``` 这样,就可以对getUserInfo接口进行访问次数限制了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值