本篇內(nèi)容主要講解“SpringBoot項目中接口防刷怎么實現(xiàn)”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“SpringBoot項目中接口防刷怎么實現(xiàn)”吧!
專注于為中小企業(yè)提供成都網(wǎng)站設計、做網(wǎng)站服務,電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)王屋免費做網(wǎng)站提供優(yōu)質(zhì)的服務。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了成百上千家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。
一、自定義注解
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.context.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) {
return true;
}
int seconds = accessLimit.seconds();
int maxCount = accessLimit.maxCount();
boolean login = accessLimit.needLogin();
String key = "1";
//如果需要登錄
if (login) {
//獲取登錄的session進行判斷
//.....
key += "" + "1"; //這里假設用戶是1,項目中是動態(tài)獲取的userId
}
//從redis中獲取用戶訪問的次數(shù)
Integer count = (Integer) redisUtil.get(key);
if (count == null) {
//第一次訪問
redisUtil.set(key, 1, seconds);
} else if (count < maxCount) {
//加1
redisUtil.incr(key, 1);
} else {
//超出訪問次數(shù)
render(response, "請求過于頻繁~請稍后再試~"); //這里的CodeMsg是一個返回參數(shù)
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;
}
}
/**
* 根據(jù)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 將設置無限期
* @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 高并發(fā)生成訂單號,秒殺類的業(yè)務邏輯等。。
*
* @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
四、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 最多請求次數(shù)
到此,相信大家對“SpringBoot項目中接口防刷怎么實現(xiàn)”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學習!
本文標題:SpringBoot項目中接口防刷怎么實現(xiàn)
本文路徑:
http://weahome.cn/article/ghjcjc.html