基于注解实现 SpringBoot 接口防刷的方法
该示例项目通过自定义注解,实现接口访问次数控制,从而实现接口防刷功能,项目结构如下:
一、编写注解类AccessLimit
packagecn.mygweb.annotation;
importjava.lang.annotation.ElementType;
importjava.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
importjava.lang.annotation.Target;
/**
*访问控制注解(实现接口防刷功能)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public@interfaceAccessLimit{
/**
*限制周期(单位为秒)
*
*@return
*/
intseconds();
/**
*规定周期内限制次数
*
*@return
*/
intmaxCount();
/**
*是否需要登录
*
*@return
*/
booleanneedLogin()defaultfalse;
}
二、在Interceptor拦截器中实现拦截逻辑
packagecn.mygweb.interceptor;
importcn.mygweb.annotation.AccessLimit;
importcn.mygweb.entity.Result;
importcn.mygweb.entity.StatusCode;
importcom.alibaba.fastjson.JSON;
importorg.springframework.stereotype.Component;
importorg.springframework.web.method.HandlerMethod;
importorg.springframework.web.servlet.handler.HandlerInterceptorAdapter;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjava.io.OutputStream;
importjava.util.HashMap;
importjava.util.Map;
/**
*访问控制拦截器
*/
@Component
publicclassAccessLimitInterceptorextendsHandlerInterceptorAdapter{
//模拟数据存储,实际业务中可以自定义实现方式
privatestaticMapaccessInfoMap=newHashMap<>();
@Override
publicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,
Objecthandler)throwsException{
//判断请求是否属于方法的请求
if(handlerinstanceofHandlerMethod){
HandlerMethodhm=(HandlerMethod)handler;
//获取方法中的注解,看是否有该注解
AccessLimitaccessLimit=hm.getMethodAnnotation(AccessLimit.class);
if(accessLimit==null){
returntrue;
}
intseconds=accessLimit.seconds();
intmaxCount=accessLimit.maxCount();
booleanneedLogin=accessLimit.needLogin();
Stringkey=request.getRequestURI();
//如果需要登录
if(needLogin){
//获取登录的session进行判断
//……
key+=""+"userA";//这里假设用户是userA,实际项目中可以改为userId
}
//模拟从redis中获取数据
AccessInfoaccessInfo=accessInfoMap.get(key);
if(accessInfo==null){
//第一次访问
accessInfo=newAccessInfo();
accessInfo.setFirstVisitTimestamp(System.currentTimeMillis());
accessInfo.setAccessCount(1);
accessInfoMap.put(key,accessInfo);
}elseif(accessInfo.getAccessCount()
三、把Interceptor注册到springboot中
packagecn.mygweb.config;
importcn.mygweb.interceptor.AccessLimitInterceptor;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;
importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*拦截器注册配置
*/
@Configuration
publicclassWebConfigimplementsWebMvcConfigurer{
@Override
publicvoidaddInterceptors(InterceptorRegistryregistry){
//注册拦截器
registry.addInterceptor(newAccessLimitInterceptor());
}
}
四、在Controller中加入注解实现接口防刷
packagecn.mygweb.controller;
importcn.mygweb.annotation.AccessLimit;
importcn.mygweb.entity.Result;
importcn.mygweb.entity.StatusCode;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/access")
publicclassAccessController{
@AccessLimit(seconds=5,maxCount=2)//访问控制,5秒内只能访问2次
@GetMapping
publicResultaccess(){
returnnewResult(true,StatusCode.OK,"访问成功!");
}
}
五、测试访问
附:StatusCode.java、Result.java、application.yml
StatusCode类
packagecn.mygweb.entity;
/**
*返回状态码
*/
publicclassStatusCode{
publicstaticfinalintOK=20000;//成功
publicstaticfinalintERROR=20001;//失败
publicstaticfinalintLOGINERROR=20002;//用户名或密码错误
publicstaticfinalintACCESSERROR=20003;//权限不足
publicstaticfinalintREMOTEERROR=20004;//远程调用失败
publicstaticfinalintREPERROR=20005;//重复操作
publicstaticfinalintNOTFOUNDERROR=20006;//没有对应的抢购数据
}
Result类:
packagecn.mygweb.entity;
importjava.io.Serializable;
/**
*响应结果
*/
publicclassResultimplementsSerializable{
privatebooleanflag;//是否成功
privateIntegercode;//返回码
privateStringmessage;//返回消息
privateTdata;//返回数据
publicResult(booleanflag,Integercode,Stringmessage,Objectdata){
this.flag=flag;
this.code=code;
this.message=message;
this.data=(T)data;
}
publicResult(booleanflag,Integercode,Stringmessage){
this.flag=flag;
this.code=code;
this.message=message;
}
publicResult(){
this.flag=true;
this.code=StatusCode.OK;
this.message="操作成功!";
}
publicbooleanisFlag(){
returnflag;
}
publicvoidsetFlag(booleanflag){
this.flag=flag;
}
publicIntegergetCode(){
returncode;
}
publicvoidsetCode(Integercode){
this.code=code;
}
publicStringgetMessage(){
returnmessage;
}
publicvoidsetMessage(Stringmessage){
this.message=message;
}
publicTgetData(){
returndata;
}
publicvoidsetData(Tdata){
this.data=data;
}
}
applications.yml:
server:
port:8080
到此这篇关于基于注解实现SpringBoot接口防刷的方法的文章就介绍到这了,更多相关SpringBoot接口防刷内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。