当前位置: 首页 > news >正文

星巴克网站建设方案/google play谷歌商店

星巴克网站建设方案,google play谷歌商店,固原网站制作,网站建设中古典武侠中文字幕SpringBoot API 接口防刷接口防刷接口防刷原理代码实现RequestLimit 注解RequestLimitIntercept 拦截器WebMvcConfig配置类Controller控制层验证接口防刷 接口防刷: 顾名思义,想让某个接口某个人在某段时间内只能请求N次。 在项目中比较常见的问题也有,…

SpringBoot API 接口防刷

  • 接口防刷
    • 接口防刷原理
    • 代码实现
      • @RequestLimit 注解
      • RequestLimitIntercept 拦截器
      • WebMvcConfig配置类
      • Controller控制层
      • 验证

接口防刷

接口防刷: 顾名思义,想让某个接口某个人在某段时间内只能请求N次。
在项目中比较常见的问题也有,那就是连点按钮导致请求多次,以前在web端有表单重复提交,可以通过token来解决。

除了上面的方法外,前后端配合的方法。现在全部由后端来控制。

接口防刷原理

在你请求的时候,服务器通过redis 记录下你请求的次数,如果次数超过限制就不给访问。
在redis 保存的key 是有时效性的,过期就会删除。

代码实现

通过自定义注解的方式实现

@RequestLimit 注解

package com.mry.springboottools.annotation;import java.lang.annotation.*;/*** 请求限制的自定义注解** @Target 注解可修饰的对象范围,ElementType.METHOD 作用于方法,ElementType.TYPE 作用于类* (ElementType)取值有:*     1.CONSTRUCTOR:用于描述构造器*     2.FIELD:用于描述域*     3.LOCAL_VARIABLE:用于描述局部变量*     4.METHOD:用于描述方法*     5.PACKAGE:用于描述包*     6.PARAMETER:用于描述参数*     7.TYPE:用于描述类、接口(包括注解类型) 或enum声明* @Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;* 而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,* 而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。* 使用这个meta-Annotation可以对 Annotation的“生命周期”限制。* (RetentionPoicy)取值有:*     1.SOURCE:在源文件中有效(即源文件保留)*     2.CLASS:在class文件中有效(即class保留)*     3.RUNTIME:在运行时有效(即运行时保留)** @Inherited* 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。* 如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。*/
@Documented
@Inherited
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLimit {// 在 second 秒内,最大只能请求 maxCount 次int second() default 1;int maxCount() default 1;
}

RequestLimitIntercept 拦截器

自定义一个拦截器,请求之前,进行请求次数校验。

package com.mry.springboottools.interceptor;import com.alibaba.fastjson.JSONObject;
import com.mry.springboottools.annotation.RequestLimit;
import com.mry.springboottools.common.ApiResultEnum;
import com.mry.springboottools.common.Result;
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.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;/*** 请求拦截* 自定义一个拦截器,请求之前,进行请求次数校验*/
@Slf4j
@Component
public class RequestLimitIntercept extends HandlerInterceptorAdapter {@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {/*** isAssignableFrom() 判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口* isAssignableFrom()方法是判断是否为某个类的父类* instanceof关键字是判断是否某个类的子类*/if(handler.getClass().isAssignableFrom(HandlerMethod.class)){//HandlerMethod 封装方法定义相关的信息,如类,方法,参数等HandlerMethod handlerMethod = (HandlerMethod) handler;Method method = handlerMethod.getMethod();// 获取方法中是否包含注解RequestLimit methodAnnotation = method.getAnnotation(RequestLimit.class);//获取 类中是否包含注解,也就是controller 是否有注解RequestLimit classAnnotation = method.getDeclaringClass().getAnnotation(RequestLimit.class);// 如果 方法上有注解就优先选择方法上的参数,否则类上的参数RequestLimit requestLimit = methodAnnotation != null?methodAnnotation:classAnnotation;if(requestLimit != null){if(isLimit(request,requestLimit)){resonseOut(response, Result.error(ApiResultEnum.REQUST_LIMIT));return false;}}}return super.preHandle(request, response, handler);}//判断请求是否受限public boolean isLimit(HttpServletRequest request,RequestLimit requestLimit){// 受限的redis 缓存key ,因为这里用浏览器做测试,我就用sessionid 来做唯一key,如果是app ,可以使用 用户ID 之类的唯一标识。String limitKey = request.getServletPath()+request.getSession().getId();// 从缓存中获取,当前这个请求访问了几次Integer redisCount = (Integer) redisTemplate.opsForValue().get(limitKey);if(redisCount == null){//初始 次数redisTemplate.opsForValue().set(limitKey,1,requestLimit.second(), TimeUnit.SECONDS);}else{if(redisCount.intValue() >= requestLimit.maxCount()){return true;}// 次数自增redisTemplate.opsForValue().increment(limitKey);}return false;}/*** 回写给客户端* @param response* @param result* @throws IOException*/private void resonseOut(HttpServletResponse response, Result result) throws IOException {response.setCharacterEncoding("UTF-8");response.setContentType("application/json; charset=utf-8");PrintWriter out = null ;String json = JSONObject.toJSON(result).toString();out = response.getWriter();out.append(json);}}

拦截器写好了,但是还得添加注册。

WebMvcConfig配置类

因为我的是Springboot2.* 所以只需实现WebMvcConfigurer
如果是springboot1.* 那就继承自 WebMvcConfigurerAdapter
然后重写addInterceptors() 添加自定义拦截器即可。

package com.mry.springboottools.config;import com.mry.springboottools.interceptor.RequestLimitIntercept;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 因为我的是Springboot2.* 所以只需实现WebMvcConfigurer* 如果是springboot1.* 那就继承自 WebMvcConfigurerAdapter* 然后重写addInterceptors() 添加自定义拦截器即可。*/
@Slf4j
@Component
public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate RequestLimitIntercept requestLimitIntercept;@Overridepublic void addInterceptors(InterceptorRegistry registry) {log.info("添加拦截");registry.addInterceptor(requestLimitIntercept);}}

Controller控制层

控制层测试接口。

使用方式:
第一种:直接在类上使用注解@RequestLimit(maxCount = 5,second = 1)
第二种:在方法上使用注解@RequestLimit(maxCount = 5,second = 1)

maxCount 最大的请求数、second 代表时间,单位是秒

默认1秒内,每个接口只能请求一次。

package com.mry.springboottools.controller;import com.mry.springboottools.annotation.RequestLimit;
import com.mry.springboottools.common.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 控制层测试接口,** 使用方式:* 第一种:直接在类上使用注解@RequestLimit(maxCount = 5,second = 1)* 第二种:在方法上使用注解@RequestLimit(maxCount = 5,second = 1)** maxCount 最大的请求数、second 代表时间,单位是秒* 默认1秒内,每个接口只能请求一次*/
@RestController
@RequestMapping("/mry")
@RequestLimit(maxCount = 5,second = 1)
public class RequestLimitController {/*** @RequestLimit 修饰在方法上,优先使用其参数* @return*/@GetMapping("/test1")@RequestLimitpublic Result test(){//TODO ...return Result.ok();}/*** @RequestLimit 修饰在类上,用的是类的参数* @return*/@GetMapping("/test2")public Result test2(){//TODO ...return Result.ok();}
}

如果在类和方法上同时有@RequestLimit注解 ,以方法上的参数为准。

验证

正常请求如下图:
在这里插入图片描述

触发接口防刷机制如下图:
在这里插入图片描述

http://www.jmfq.cn/news/4946041.html

相关文章:

  • 做食品网站有哪些/太原模板建站定制网站
  • 怎么用虚拟主机做网站/网络营销工程师培训
  • 哪家网站推广做的好/一键优化清理
  • 2017优秀网站设计/网络营销的方法包括哪些
  • 网站建设开发流程按钮/百度人工
  • wordpress网站专题/深圳seo公司排名
  • 网站开发款计入什么科目/宁波网站推广排名
  • 小程序免费制作平台有吗/seo优化技术厂家
  • 计算机怎么建设网站/seo诊断书
  • 做农产品网站需要做的准备/关键词优化设计
  • 开源html5 网站模板/巨量算数关键词查询
  • 网站备案与域名备案/深圳网络推广案例
  • 做网站免费/河南做网站的
  • 什么网站免费做游戏/江北seo综合优化外包
  • 怎么用PS做网站横幅/热搜榜百度一下你就知道
  • wordpress怎样搭建外贸网站/seo实战密码第四版pdf
  • 免费做封面的网站/抖音搜索排名
  • 重庆建设集团官方网站/肇庆seo按天收费
  • 做网站一般注册商标哪个类/网址之家大全
  • 柳州住房和城乡建设部网站/良品铺子网络营销策划书
  • 临安网站设计/网站seo文章该怎么写
  • 惠州做网站的/百度搜索推广操作简要流程
  • 建设部网站官网 下载规范/品牌词优化
  • 宁波免费做网站/合肥建站公司seo
  • 网上做任务的网站有哪些/资阳市网站seo
  • 深圳做营销网站的公司简介/靖江seo要多少钱
  • 做导航网站用多大的空间/如何免费搭建自己的网站
  • 全国建设部网站/开源crm系统
  • 网站图片怎么做优化/nba录像回放
  • wordpress文章列分页/廊坊推广seo霸屏