手机网站做的比较好的,建设工程合同可以分为,山东泰润建设集团网站,微信公众平台小程序管理在哪里写一个RedisService#xff0c;实现获取Redis 的set、get、incr#xff08;相当于计数器#xff09; 写inferface注解类 做一个拦截器#xff0c;因为要先于控制器判断 将拦截器注入Springboot 文章目录 目录 文章目录 前言 一、引入依赖 二、使用步骤 2.1 RedisServic… 写一个RedisService实现获取Redis 的set、get、incr相当于计数器 写inferface注解类 做一个拦截器因为要先于控制器判断 将拦截器注入Springboot 文章目录 目录 文章目录 前言 一、引入依赖 二、使用步骤 2.1 RedisService操作redis 2.2 防刷的自定义注解 2.3 自定义的过滤器 2.4 测试的控制类 2.5 测试结果 总结 前言 一、引入依赖
dependency
groupIdorg.springframework.boot/groupId
artifactIdspring-boot-starter-data-redis/artifactId
/dependencydependencygroupIdcom.alibaba/groupId
artifactIdfastjson/artifactId
version1.2.78/version
/dependency
application.properties
spring.redis.port6379
spring.redis.host127.0.0.1
spring.redis.password123456
二、使用步骤
2.1 RedisService操作redis
Service
public class RedisService {private final StringRedisTemplate stringRedisTemplate;Autowiredpublic RedisService(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate;}public void set(String key, String value) {ValueOperationsString, String operations stringRedisTemplate.opsForValue();operations.set(key, value, 1, TimeUnit.MINUTES); // 设置值时设置过期时间为1分钟}public void set(String key, String value,int N) {ValueOperationsString, String operations stringRedisTemplate.opsForValue();operations.set(key, value, N, TimeUnit.MINUTES); // 设置值时设置过期时间为N分钟}public String get(String key) {ValueOperationsString, String operations stringRedisTemplate.opsForValue();return operations.get(key);}public Long incr(String key, long delta) {return performIncrement(key, delta);}public Long incr(String key) {return performIncrement(key, 1); // 使用默认增量 1}private Long performIncrement(String key, long delta) {ValueOperationsString, String operations stringRedisTemplate.opsForValue();// 检查键是否存在如果不存在则设置初始值为 0 并设置过期时间if (Boolean.FALSE.equals(stringRedisTemplate.hasKey(key))) {operations.set(key, 0, 1, TimeUnit.MINUTES); // 设置过期时间为 1 分钟}return operations.increment(key, delta);}
}2.2 防刷的自定义注解
Retention(RUNTIME)
Target(METHOD)
public interface AccessLimit {//每分钟int minutes();//访问的次数限制int maxCount();
//是否需要登录boolean needLogin()default true;
}2.3 自定义的过滤器
过滤器主要是访问的时候 处理加了防刷注解的接口 然后限制访问给出不一样的返回结果
Component
public class PreventRefreshInterceptor extends HandlerInterceptorAdapter {Autowiredprivate RedisService redisService;Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(进入拦截器);//判断请求是否属于方法的请求if(handler instanceof HandlerMethod){System.out.println(判断请求是否属于方法的请求);HandlerMethod hm (HandlerMethod) handler;//获取方法中的注解,看是否有该注解AccessLimit accessLimit hm.getMethodAnnotation(AccessLimit.class);if(accessLimit null){return true;}//AccessLimit(seconds5, maxCount5, needLogintrue)int minutes accessLimit.minutes();int maxCount accessLimit.maxCount();boolean login accessLimit.needLogin();MapString, Object mpnew HashMap();mp.put(seconds,minutes);mp.put(maxCount,maxCount);mp.put(login,login);System.out.println(mp);String key IPUtil.getIpAddr(request)_request.getRequestURI();log.error(Key:{},key);//如果需要登录
// if(login){
// redisService.set(key, 1);
// }//从redis中获取用户访问的次数String value redisService.get(key);System.out.println(value:value);//判断value是否为nullif(value null){System.out.println(第1次访问设置有效期minutes 分钟);redisService.set(key, 1,minutes);}else{Long count redisService.incr(key);System.out.println(第count次访问设置有效期minutes 分钟);System.out.println({count :count , maxCount :maxCount});if(count.intValue() maxCount){System.out.println(超出访问次数);redisService.set(key, 超出次数);renderError(response);}}}return true;}private void renderError(HttpServletResponse response)throws Exception {response.setContentType(application/json;charsetUTF-8);OutputStream out response.getOutputStream();String str JSON.toJSONString(ResultT.error(error,超出访问次数));out.write(str.getBytes(UTF-8));out.flush();out.close();}
}
把修改后的过滤器给spring mvc的web过滤器
Configuration
public class WebConfig extends WebMvcConfigurerAdapter {Autowiredprivate PreventRefreshInterceptor interceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {System.out.println(进入拦截器配置类);registry.addInterceptor(interceptor);}
}
2.4 测试的控制类
RestController
public class RefreshController {AccessLimit(minutes2, maxCount10, needLogintrue)RequestMapping(/shua)ResponseBodypublic ResultT shua(){return ResultT.ok(请求成功);}}
统一结果类
public class ResultT extends HashMapString, Object {public ResultT() {put(code, 0);put(msg, success);}public static ResultT ok() {ResultT t new ResultT();t.put(msg, 操作成功);return t;}public static ResultT ok(String msg) {ResultT t new ResultT();t.put(msg, msg);return t;}public static ResultT ok(MapString, Object map) {ResultT t new ResultT();map.putAll(t);return t;}public static ResultT error(String code,String msg) {ResultT t new ResultT();t.put(code, code);t.put(msg, msg);return t;}public static ResultT error(String msg) {return error(500, msg);}public ResultT put(String key, Object value){super.put(key, value);return this;}
}public class IPUtil {private static final String UNKNOWN unknown;protected IPUtil() {}/*** 获取 IP地址* 使用 Nginx等反向代理软件 则不能通过 request.getRemoteAddr()获取 IP地址* 如果使用了多级反向代理的话X-Forwarded-For的值并不止一个而是一串IP地址* X-Forwarded-For中第一个非 unknown的有效IP字符串则为真实IP地址*/public static String getIpAddr(HttpServletRequest request) {String ip request.getHeader(x-forwarded-for);if (ip null || ip.length() 0 || UNKNOWN.equalsIgnoreCase(ip)) {ip request.getHeader(Proxy-Client-IP);}if (ip null || ip.length() 0 || UNKNOWN.equalsIgnoreCase(ip)) {ip request.getHeader(WL-Proxy-Client-IP);}if (ip null || ip.length() 0 || UNKNOWN.equalsIgnoreCase(ip)) {ip request.getRemoteAddr();}return 0:0:0:0:0:0:0:1.equals(ip) ? 127.0.0.1 : ip;}}
2.5 测试结果 总结