欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java后端限制頻繁請求和重復(fù)提交的實(shí)現(xiàn)

 更新時間:2022年04月12日 08:38:42   作者:墨著染霜華  
很多用戶會請求過于頻繁或者是多次重復(fù)提交數(shù)據(jù),本文主要介紹了Java后端限制頻繁請求和重復(fù)提交的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

當(dāng)前端按連續(xù)請求多次,請求過于頻繁或者是多次重復(fù)提交數(shù)據(jù),對系統(tǒng)或者是數(shù)據(jù)造成了一點(diǎn)的損害。

為了解決這個問題,下面介紹了一種簡易的解決方法:

步驟一、寫限制注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * @Author Minco
 * @Date 16:04 2020-08-13
 * @Description 不重復(fù)提交注解
 */
 
@Target(ElementType.METHOD) // 作用到方法上
@Retention(RetentionPolicy.RUNTIME) // 運(yùn)行時有效
public @interface NoRepeatSubmit {
 
    String name() default "name:";
}

步驟二、解析注解

import javax.servlet.http.HttpServletRequest;
import com.hieasy.comm.core.domain.R;
import com.hieasy.comm.redis.service.RedisService;
import com.hieasy.system.util.TermUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.concurrent.TimeUnit;
 
 
/**
 * @Author Minco
 * @Date 16:02 2020-08-13
 * @Description aop解析注解
 */
 
@Aspect
@Component
public class NoRepeatSubmitAop {
 
    private Log logger = LogFactory.getLog(getClass());
 
    @Autowired
    private RedisService redisService;
 
    @Around("execution(* com.hieasy.*.controller.*.*Ctrl.*(..)) && @annotation(nrs)")
    public Object arround(ProceedingJoinPoint pjp, NoRepeatSubmit nrs) throws Throwable {
       
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            String key = TermUtil.getUserId() + "-" + request.getServletPath();
            if ( !redisService.haskey(key) ) {// 如果緩存中有這個url視為重復(fù)提交
                Object o = pjp.proceed();
                redisService.setCacheObject(key, 0, 15, TimeUnit.SECONDS);
                return o;
            } else {
                redisService.setCacheObject(key, 0, 15, TimeUnit.SECONDS);//點(diǎn)了同樣的URL繼續(xù)限制,直到2次點(diǎn)擊中間間隔超過了限制
                return R.error("請勿重復(fù)提交或者操作過于頻繁!");
            }
    
    }
 
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
 
import java.util.*;
import java.util.concurrent.TimeUnit;
 
/**
 * @Author Minco
 * @Date 13:55 2020-06-23
 * @Description RedisService
 */
@Component
@SuppressWarnings(value = {"unchecked", "rawtypes"})
public class RedisService {
 
    @Autowired
    public RedisTemplate redisTemplate;
 
    /**
     * 緩存基本的對象,Integer、String、實(shí)體類等
     *
     * @param key   緩存的鍵值
     * @param value 緩存的值
     * @return 緩存的對象
     */
    public <T> ValueOperations<String, T> setCacheObject(String key, T value) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key, value);
        return operation;
    }
 
    /**
     * 緩存基本的對象,Integer、String、實(shí)體類等
     *
     * @param key      緩存的鍵值
     * @param value    緩存的值
     * @param timeout  時間
     * @param timeUnit 時間顆粒度
     * @return 緩存的對象
     */
    public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key, value, timeout, timeUnit);
        return operation;
    }
 
    /**
     * 獲得緩存的基本對象。
     *
     * @param key 緩存鍵值
     * @return 緩存鍵值對應(yīng)的數(shù)據(jù)
     */
    public <T> T getCacheObject(String key) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }
 
    /**
     * 刪除單個對象
     *
     * @param key
     */
    public void deleteObject(String key) {
        redisTemplate.delete(key);
    }
 
    /**
     * 刪除集合對象
     *
     * @param collection
     */
    public void deleteObject(Collection collection) {
        redisTemplate.delete(collection);
    }
 
    /**
     * 緩存List數(shù)據(jù)
     *
     * @param key      緩存的鍵值
     * @param dataList 待緩存的List數(shù)據(jù)
     * @return 緩存的對象
     */
    public <T> ListOperations<String, T> setCacheList(String key, List<T> dataList) {
        ListOperations listOperation = redisTemplate.opsForList();
        if (null != dataList) {
            int size = dataList.size();
            for (int i = 0; i < size; i++) {
                listOperation.leftPush(key, dataList.get(i));
            }
        }
        return listOperation;
    }
 
    /**
     * 獲得緩存的list對象
     *
     * @param key 緩存的鍵值
     * @return 緩存鍵值對應(yīng)的數(shù)據(jù)
     */
    public <T> List<T> getCacheList(String key) {
        List<T> dataList = new ArrayList<T>();
        ListOperations<String, T> listOperation = redisTemplate.opsForList();
        Long size = listOperation.size(key);
 
        for (int i = 0; i < size; i++) {
            dataList.add(listOperation.index(key, i));
        }
        return dataList;
    }
 
    /**
     * 緩存Set
     *
     * @param key     緩存鍵值
     * @param dataSet 緩存的數(shù)據(jù)
     * @return 緩存數(shù)據(jù)的對象
     */
    public <T> BoundSetOperations<String, T> setCacheSet(String key, Set<T> dataSet) {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        Iterator<T> it = dataSet.iterator();
        while (it.hasNext()) {
            setOperation.add(it.next());
        }
        return setOperation;
    }
 
    /**
     * 獲得緩存的set
     *
     * @param key
     * @return
     */
    public <T> Set<T> getCacheSet(String key) {
        Set<T> dataSet = new HashSet<T>();
        BoundSetOperations<String, T> operation = redisTemplate.boundSetOps(key);
        dataSet = operation.members();
        return dataSet;
    }
 
    /**
     * 緩存Map
     *
     * @param key
     * @param dataMap
     * @return
     */
    public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {
        HashOperations hashOperations = redisTemplate.opsForHash();
        if (null != dataMap) {
            for (Map.Entry<String, T> entry : dataMap.entrySet()) {
                hashOperations.put(key, entry.getKey(), entry.getValue());
            }
        }
        return hashOperations;
    }
 
    /**
     * 獲得緩存的Map
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> getCacheMap(String key) {
        Map<String, T> map = redisTemplate.opsForHash().entries(key);
        return map;
    }
 
    /**
     * 獲得緩存的基本對象列表
     *
     * @param pattern 字符串前綴
     * @return 對象列表
     */
    public Collection<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }
 
    /**
     *
     * @param key
     * @return
     */
    public boolean  haskey(String key){
        return redisTemplate.hasKey(key);
    }
 
    public Long getExpire(String key){
       return redisTemplate.getExpire(key);
    }
 
 
    public <T> ValueOperations<String, T> setBillObject(String key, List<Map<String, Object>> value) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key, (T) value);
        return operation;
    }
    /**
     * 緩存list<Map<String, Object>>
     *
     * @param key      緩存的鍵值
     * @param value    緩存的值
     * @param timeout  時間
     * @param timeUnit 時間顆粒度
     * @return 緩存的對象
     */
    public <T> ValueOperations<String, T> setBillObject(String key, List<Map<String, Object>> value, Integer timeout, TimeUnit timeUnit) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key,(T)value, timeout, timeUnit);
        return operation;
    }
    /**
     * 緩存Map
     *
     * @param key
     * @param dataMap
     * @return
     */
    public <T> HashOperations<String, String, T> setCKdBillMap(String key, Map<String, T> dataMap) {
        HashOperations hashOperations = redisTemplate.opsForHash();
        if (null != dataMap) {
            for (Map.Entry<String, T> entry : dataMap.entrySet()) {
                hashOperations.put(key, entry.getKey(), entry.getValue());
            }
        }
        return hashOperations;
    }
}

步驟三、控制層注解使用

    @NoRepeatSubmit
    @PostMapping("insert")
    @OperLog(title = "倉庫調(diào)整", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增倉庫調(diào)整單", notes = "")
    public R insert(@RequestBody Cktzd cktzd) {
        System.out.println(JSON.toJSONString(cktzd));
        return R.error("測試階段!");
    }

 測試結(jié)果:

第一次提交

在不間隔15就繼續(xù)點(diǎn)

不間斷的點(diǎn),只要2次點(diǎn)擊之間沒有超過15秒,都會拋出請勿重復(fù)請求。直到2次點(diǎn)擊之間間隔足夠才能正常請求! 

到此這篇關(guān)于Java后端限制頻繁請求和重復(fù)提交的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java后端限制頻繁請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 高并發(fā)七:并發(fā)設(shè)計模型詳解

    Java 高并發(fā)七:并發(fā)設(shè)計模型詳解

    本文主要介紹Java高并發(fā) 并發(fā)設(shè)計模型的知識,這里主要講解 1. 什么是設(shè)計模式 2. 單例模式 3. 不變模式 4. Future模式 5. 生產(chǎn)者消費(fèi)者,有需要的小伙伴可以參考下
    2016-09-09
  • Java語言class類用法及泛化(詳解)

    Java語言class類用法及泛化(詳解)

    這篇文章主要介紹了Java語言class類用法及泛化(詳解),大家都知道Java程序在運(yùn)行過程中,對所有的對象今夕類型標(biāo)識,也就是RTTI。這項(xiàng)信息記錄了每個對象所屬的類,需要的朋友可以參考下
    2015-07-07
  • Java HttpClient實(shí)現(xiàn)socks代理的示例代碼

    Java HttpClient實(shí)現(xiàn)socks代理的示例代碼

    這篇文章主要介紹了Java HttpClient 實(shí)現(xiàn) socks 代理的示例代碼,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-11-11
  • java實(shí)現(xiàn)1M圖片壓縮優(yōu)化到100kb實(shí)現(xiàn)示例

    java實(shí)現(xiàn)1M圖片壓縮優(yōu)化到100kb實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了java實(shí)現(xiàn)1M圖片壓縮優(yōu)化到100kb示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Java中LinkedHashSet的源碼剖析

    Java中LinkedHashSet的源碼剖析

    這篇文章主要介紹了Java中LinkedHashSet的源碼剖析,LinkedHashSet是HashSet的子類,LinkedHashSet底層是一個LinkedHashMap,底層維護(hù)了一個數(shù)組+雙向鏈表,需要的朋友可以參考下
    2023-09-09
  • java編程的30個建議

    java編程的30個建議

    這篇文章主要介紹了java編程的30個建議,需要的朋友可以參考下
    2014-05-05
  • 使用Java代碼將IP地址轉(zhuǎn)換為int類型的方法

    使用Java代碼將IP地址轉(zhuǎn)換為int類型的方法

    這篇文章主要介紹了使用Java代碼將IP地址轉(zhuǎn)換為int類型的方法,這也是各大計算機(jī)考試和ACM以及面試的常見基礎(chǔ)問題,需要的朋友可以參考下
    2015-08-08
  • 使用jpa的時候set實(shí)體類屬性自動持久化的解決方案

    使用jpa的時候set實(shí)體類屬性自動持久化的解決方案

    這篇文章主要介紹了使用jpa的時候set實(shí)體類屬性自動持久化的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 詳解SpringBoot中時間類型的序列化與反序列化

    詳解SpringBoot中時間類型的序列化與反序列化

    這篇文章主要為大家詳細(xì)介紹了SpringBoot中時間類型的序列化與反序列化的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-02-02
  • SpringBoot yml配置文件調(diào)用過程解析

    SpringBoot yml配置文件調(diào)用過程解析

    這篇文章主要介紹了SpringBoot yml配置文件調(diào)用過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11

最新評論