SpringBoot项目中接口防刷的完整代码

网友投稿 383 2022-12-28

SpringBoot项目中接口防刷的完整代码

一、自定义注解

import java.lang.annotation.Retention;

import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.METHOD;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**

* @author Yang

* @version 1.0

* @date 2021/2/22 10:28

*/

@Retention(RUNTIME)

@Target(METHOD)

public @interface AccessLimit {

int seconds();

int maxCount();

boolean needLogin() default true;

}

二、定义拦截器

import com.alibaba.fastjson.JSON;

import com.mengxiangnongfu.payment.annotation.AccessLimit;

import com.mengxiangnongfu.payment.commons.RedisUtil;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.contehttp://xt.annotation.Configuration;

import org.springframework.stereotype.Component;

import org.springframework.web.method.HandlerMethod;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.OutputStream;

/**

* @author Yang

* @version 1.0

* @date 2021/2/22 10:29

*/

@Component

public class FangshuaInterceptor extends HandlerInterceptorAdapter {

@Autowired

private RedisUtil redisUtil;

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

//判断请求是否属于方法的请求

if (handler instanceof HandlerMethod) {

HandlerMethod hm = (HandlerMethod) handler;

//获取方法中的注解,看是否有该注解

AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);

if (accessLimit == null) {

rethttp://urn true;

}

int seconds = accessLimit.seconds();

int maxCount = accessLimit.maxCount();

boolean login = accessLimit.needLogin();

String key = "1";

//如果需要登录

if (login) {

//获取登录的session进行判断

//.....

key += "" + "1"; //这里假设用户是1,项目中是动态获取的userId

}

//从redis中获取用户访问的次数

Integer count = (Integer) redisUtil.get(key);

if (count == null) {

//第一次访问

redisUtil.set(key, 1, seconds);

} else if (count < maxCount) {

//加1

redisUtil.incr(key, 1);

} else {

//超出访问次数

render(response, "请求过于频繁~请稍后再试~"); //这里的CodeMsg是一个返回参数

return false;

}

}

return true;

}

private void render(HttpServletResponse response, String cm) throws Exception {

response.setContentType("application/json;charset=UTF-8");

OutputStream out = response.getOutputStream();

String str = JSON.toJSONString(cm);

out.write(str.getBytes("UTF-8"));

out.flush();

out.close();

}

}

三、Redis工具类

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.stereotype.Component;

import org.springframework.util.CollectionUtils;

import java.util.List;

import java.util.Map;

import java.util.Set;

import java.util.concurrent.TimeUnit;

/**

* @author Yang

* @version 1.0

* @date 2020/11/29 17:06

*/

@Component

@Slf4j

public class RedisUtil {

@Autowired

RedisTemplate redisTemplate;

// =============================common============================

/**

* 指定缓存失效时间

*

* @param key 键

* @param time 时间(秒)

* @return

*/

public boolean expire(String key, long time) {

try {

if (time > 0) {

redisTemplate.expire(key, time, TimeUnit.SECONDS);

}

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 根据key 获取过期时间

*

* @param key 键 不能为null

* @return 时间(秒) 返回0代表为永久有效

*/

public long getExpire(String key) {

return redisTemplate.getExpire(key, TimeUnit.SECONDS);

}

/**

* 判断key是否存在

*

* @param key 键

* @return true 存在 false不存在

*/

public boolean hasKey(String key) {

try {

return redisTemplate.hasKey(key);

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 删除缓存

*

* @param key 可以传一个值 或多个

*/

@SuppressWarnings("unchecked")

public void del(String... key) {

if (key != null && key.length > 0) {

if (key.length == 1) {

redisTemplate.delete(key[0]);

} else {

redisTemplate.delete(CollectionUtils.arrayToList(key));

}

}

}

// ============================String=============================

/**

* 普通缓存获取

*

* @param key 键

* @return 值

*/

public Object get(String key) {

return key == null ? null : redisTemplate.opsForValue().get(key);

}

/**

* 普通缓存放入

*

* @param key 键

* @param value 值

* @return true成功 false失败

*/

public boolean set(String key, Object value) {

try {

redisTemplate.opsForValue().set(key, value);

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 普通缓存放入并设置时间

*

* @param key 键

* @param value 值

* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限http://期

* @return true成功 false 失败

*/

public boolean set(String key, Object value, long time) {

try {

if (time > 0) {

redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);

} else {

set(key, value);

}

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 递增 适用场景: https://blog.csdn.net/y_y_y_k_k_k_k/article/details/79218254 高并发生成订单号,秒杀类的业务逻辑等。。

*

* @param key 键

* @param delta 要增加几(大于0)

* @return

*/

public long incr(String key, long delta) {

if (delta < 0) {

throw new RuntimeException("递增因子必须大于0");

}

return redisTemplate.opsForValue().increment(key, delta);

}

/**

* 递减

*

* @param key 键

* @param delta 要减少几(小于0)

* @return

*/

public long decr(String key, long delta) {

if (delta < 0) {

throw new RuntimeException("递减因子必须大于0");

}

return redisTemplate.opsForValue().increment(key, -delta);

}

// ================================Map=================================

/**

* HashGet

*

* @param key 键 不能为null

* @param item 项 不能为null

* @return 值

*/

public Object hget(String key, String item) {

return redisTemplate.opsForHash().get(key, item);

}

/**

* 获取hashKey对应的所有键值

*

* @param key 键

* @return 对应的多个键值

*/

public Map hmget(String key) {

return redisTemplate.opsForHash().entries(key);

}

/**

* HashSet

*

* @param key 键

* @param map 对应多个键值

* @return true 成功 false 失败

*/

public boolean hmset(String key, Map map) {

try {

redisTemplate.opsForHash().putAll(key, map);

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* HashSet 并设置时间

*

* @param key 键

* @param map 对应多个键值

* @param time 时间(秒)

* @return true成功 false失败

*/

public boolean hmset(String key, Map map, long time) {

try {

redisTemplate.opsForHash().putAll(key, map);

if (time > 0) {

expire(key, time);

}

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 向一张hash表中放入数据,如果不存在将创建

*

* @param key 键

* @param item 项

* @param value 值

* @return true 成功 false失败

*/

public boolean hset(String key, String item, Object value) {

try {

redisTemplate.opsForHash().put(key, item, value);

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 向一张hash表中放入数据,如果不存在将创建

*

* @param key 键

* @param item 项

* @param value 值

* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间

* @return true 成功 false失败

*/

public boolean hset(String key, String item, Object value, long time) {

try {

redisTemplate.opsForHash().put(key, item, value);

if (time > 0) {

expire(key, time);

}

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 删除hash表中的值

*

* @param key 键 不能为null

* @param item 项 可以使多个 不能为null

*/

public void hdel(String key, Object... item) {

redisTemplate.opsForHash().delete(key, item);

}

/**

* 判断hash表中是否有该项的值

*

* @param key 键 不能为null

* @param item 项 不能为null

* @return true 存在 false不存在

*/

public boolean hHasKey(String key, String item) {

return redisTemplate.opsForHash().hasKey(key, item);

}

/**

* hash递增 如果不存在,就会创建一个 并把新增后的值返回

*

* @param key 键

* @param item 项

* @param by 要增加几(大于0)

* @return

*/

public double hincr(String key, String item, double by) {

return redisTemplate.opsForHash().increment(key, item, by);

}

/**

* hash递减

*

* @param key 键

* @param item 项

* @param by 要减少记(小于0)

* @return

*/

public double hdecr(String key, String item, double by) {

return redisTemplate.opsForHash().increment(key, item, -by);

}

// ============================set=============================

/**

* 根据key获取Set中的所有值

*

* @param key 键

* @return

*/

public Set sGet(String key) {

try {

return redisTemplate.opsForSet().members(key);

} catch (Exception e) {

log.error(key, e);

return null;

}

}

/**

* 根据value从一个set中查询,是否存在

*

* @param key 键

* @param value 值

* @return true 存在 false不存在

*/

public boolean sHasKey(String key, Object value) {

try {

return redisTemplate.opsForSet().isMember(key, value);

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 将数据放入set缓存

*

* @param key 键

* @param values 值 可以是多个

* @return 成功个数

*/

public long sSet(String key, Object... values) {

try {

return redisTemplate.opsForSet().add(key, values);

} catch (Exception e) {

log.error(key, e);

return 0;

}

}

/**

* 将set数据放入缓存

*

* @param key 键

* @param time 时间(秒)

* @param values 值 可以是多个

* @return 成功个数

*/

public long sSetAndTime(String key, long time, Object... values) {

try {

Long count = redisTemplate.opsForSet().add(key, values);

if (time > 0) {

expire(key, time);

}

return count;

} catch (Exception e) {

log.error(key, e);

return 0;

}

}

/**

* 获取set缓存的长度

*

* @param key 键

* @return

*/

public long sGetSetSize(String key) {

try {

return redisTemplate.opsForSet().size(key);

} catch (Exception e) {

log.error(key, e);

return 0;

}

}

/**

* 移除值为value的

*

* @param key 键

* @param values 值 可以是多个

* @return 移除的个数

*/

public long setRemove(String key, Object... values) {

try {

Long count = redisTemplate.opsForSet().remove(key, values);

return count;

} catch (Exception e) {

log.error(key, e);

return 0;

}

}

// ============================zset=============================

/**

* 根据key获取Set中的所有值

*

* @param key 键

* @return

*/

public Set zSGet(String key) {

try {

return redisTemplate.opsForSet().members(key);

} catch (Exception e) {

log.error(key, e);

return null;

}

}

/**

* 根据value从一个set中查询,是否存在

*

* @param key 键

* @param value 值

* @return true 存在 false不存在

*/

public boolean zSHasKey(String key, Object value) {

try {

return redisTemplate.opsForSet().isMember(key, value);

} catch (Exception e) {

log.error(key, e);

return false;

}

}

public Boolean zSSet(String key, Object value, double score) {

try {

return redisTemplate.opsForZSet().add(key, value, 2);

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 将set数据放入缓存

*

* @param key 键

* @param time 时间(秒)

* @param values 值 可以是多个

* @return 成功个数

*/

public long zSSetAndTime(String key, long time, Object... values) {

try {

Long count = redisTemplate.opsForSet().add(key, values);

if (time > 0) {

expire(key, time);

}

return count;

} catch (Exception e) {

log.error(key, e);

return 0;

}

}

/**

* 获取set缓存的长度

*

* @param key 键

* @return

*/

public long zSGetSetSize(String key) {

try {

return redisTemplate.opsForSet().size(key);

} catch (Exception e) {

log.error(key, e);

return 0;

}

}

/**

* 移除值为value的

*

* @param key 键

* @param values 值 可以是多个

* @return 移除的个数

*/

public long zSetRemove(String key, Object... values) {

try {

Long count = redisTemplate.opsForSet().remove(key, values);

return count;

} catch (Exception e) {

log.error(key, e);

return 0;

}

}

// ===============================list=================================

/**

* 获取list缓存的内容

*

* @param key 键

http://* @param start 开始 0 是第一个元素

* @param end 结束 -1代表所有值

* @return

* @取出来的元素 总数 end-start+1

*/

public List lGet(String key, long start, long end) {

try {

return redisTemplate.opsForList().range(key, start, end);

} catch (Exception e) {

log.error(key, e);

return null;

}

}

/**

* 获取list缓存的长度

*

* @param key 键

* @return

*/

public long lGetListSize(String key) {

try {

return redisTemplate.opsForList().size(key);

} catch (Exception e) {

log.error(key, e);

return 0;

}

}

/**

* 通过索引 获取list中的值

*

* @param key 键

* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推

* @return

*/

public Object lGetIndex(String key, long index) {

try {

return redisTemplate.opsForList().index(key, index);

} catch (Exception e) {

log.error(key, e);

return null;

}

}

/**

* 将list放入缓存

*

* @param key 键

* @param value 值

* @return

*/

public boolean lSet(String key, Object value) {

try {

redisTemplate.opsForList().rightPush(key, value);

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 将list放入缓存

*

* @param key 键

* @param value 值

* @param time 时间(秒)

* @return

*/

public boolean lSet(String key, Object value, long time) {

try {

redisTemplate.opsForList().rightPush(key, value);

if (time > 0) {

expire(key, time);

}

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 将list放入缓存

*

* @param key 键

* @param value 值

* @return

*/

public boolean lSet(String key, List value) {

try {

redisTemplate.opsForList().rightPushAll(key, value);

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 将list放入缓存

*

* @param key 键

* @param value 值

* @param time 时间(秒)

* @return

*/

public boolean lSet(String key, List value, long time) {

try {

redisTemplate.opsForList().rightPushAll(key, value);

if (time > 0) {

expire(key, time);

}

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 根据索引修改list中的某条数据

*

* @param key 键

* @param index 索引

* @param value 值

* @return

*/

public boolean lUpdateIndex(String key, long index, Object value) {

try {

redisTemplate.opsForList().set(key, index, value);

return true;

} catch (Exception e) {

log.error(key, e);

return false;

}

}

/**

* 移除N个值为value

*

* @param key 键

* @param count 移除多少个

* @param value 值

* @return 移除的个数

*/

public long lRemove(String key, long count, Object value) {

try {

Long remove = redisTemplate.opsForList().remove(key, count, value);

return remove;

} catch (Exception e) {

log.error(key, e);

return 0;

}

}

}

四、POM文件

org.springframework.boot

spring-boot-starter-aop

org.springframework.boot

spring-boot-starter-data-redis

记得配置redis的连接

在需要拦截的地方加入注解即可@AccessLimit(seconds = 5, maxCount = 1, needLogin = false) seconds重置访问频率时间 maxCount 最多请求次数

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java面试题冲刺第七天
下一篇:网站信息统计 API接口(网站信息统计 api接口)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~