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

自定义spring拦截器

说明:

一些版本比较老的spring框架的,是通过继承HandlerInterceptorAdapter并重写preHandle()方法,和继承WebMvcConfigurerAdapter并重写 addInterceptors()方法来实现拦截器的,但是这两个类很久前就已经过时了,不推荐使用,推荐使用下面两个接口。

以接口接口限流进行具体的操作,自定义拦截器主要步骤就是两个:

1、实现HandlerInterceptor,并实现rpreHandle()前置处理方法

2、实现WebMvcConfigurer,并实现addInterceptors()增加拦截器方法,把自定义的拦截器增加到spring容器中

HandlerInterceptor拦截器处理器接口有三个接口
● preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
● postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView ;
● afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);

实操:

1、引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--Redis依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、自定义接口访问注解

/**
* 接口访问限制枚举
* @author ppp
* @date 2023/2/14
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {/*** @return 访问最大次数*/int accessMaxTimes() default 60;/*** @return 时间*/long timeOut() default 1;/*** @return 时间单位*/TimeUnit timeUnit() default TimeUnit.MINUTES;
}

3、自定义拦截器配置

同时实现HandlerInterceptor,WebMvcConfigurer,实现preHandle()和addInterceptors()方法

/**
* 接口访问限制拦截器配置
* @author ppp
* @date 2023/2/14
*/
@Component
public class AccessLimitInterceptorConfig implements HandlerInterceptor, WebMvcConfigurer {private final static String KEY = "Redis_accessLimit_key";@AutowiredRedisTemplate redisTemplate;@AutowiredAccessLimitInterceptorConfig accessLimitInterceptorConfig;@Overridepublic 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 accessMaxTimes = accessLimit.accessMaxTimes();long timeOut = accessLimit.timeOut();TimeUnit timeUnit = accessLimit.timeUnit();// 如果redis不存在或已经过期Long expire =redisTemplate.opsForValue().getOperations().getExpire(KEY);if (!redisTemplate.hasKey(KEY) ||  Objects.requireNonNull(expire).intValue() < 0) {redisTemplate.opsForValue().set(KEY, 1, timeOut, timeUnit);} else {long increment = redisTemplate.opsForValue().increment(KEY).intValue();if (increment > accessMaxTimes) {throw new RuntimeException("访问已经超过最大值: " + accessMaxTimes);}}}return true;}@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(accessLimitInterceptorConfig);}
}

4、配置redis

/*** Redis管理配置*/
@Configuration
public class RedisConfigurer {/*** 设置 redisTemplate 的序列化设置** @param redisConnectionFactory* @return*/@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);GenericToStringSerializer genericToStringSerializer = new GenericToStringSerializer(Object.class);template.setValueSerializer(genericToStringSerializer);template.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer(Charset.forName("UTF-8")));template.setHashValueSerializer(new StringRedisSerializer(Charset.forName("UTF-8")));template.afterPropertiesSet();return template;}@Beanpublic CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),this.getRedisCacheConfigurationWithTtl(24 * 60 * 60), // 默认策略,未配置的 key 会使用这个this.getRedisCacheConfigurationMap() // 指定 key 策略);}private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();return redisCacheConfigurationMap;}private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(seconds));return redisCacheConfiguration;}
}

5、使用

/*** 一分钟内最多请求10次* @param content*/
@AccessLimit(accessMaxTimes = 10, timeOut = 1, timeUnit = TimeUnit.MINUTES)
@GetMapping("/sendEvent")
public void sendEvent(@RequestParam String content) {testService.send(content);
}
http://www.lryc.cn/news/8375.html

相关文章:

  • 今天正式上线!虹科汽车免拆诊断云展厅:感受精准修车魅力,畅享汽修领先技术
  • 4.数据类型-字符串【Python】
  • 搞量化先搞数(上):A股股票列表免费抓取实战
  • SpringCloud-负载均衡Ribbon
  • Linux入门篇(二)
  • 第四部分:特殊用途的句子——第三章:虚拟
  • Java中如何获取泛型类型信息
  • 【云原生】centos7搭建安装k8s集群 v1.25版本详细教程实战
  • c语言指针
  • 5.33 综合案例2.0 -ESP32拍照上传阿里云OSS
  • java无重复字符的最长子串
  • 测试用例设计工作中的应用
  • leetcode 困难 —— 数字 1 的个数(简单逻辑题)
  • 关于JSON
  • Apifox-接口调用、自动化测试工具
  • Vue一个项目兼容每个省份的个性化需求
  • npm install报错 npm ERR! 的解决办法
  • echarts修改饼图,环形图的圆环宽度,大小
  • 小白系列Vite-Vue3-TypeScript:010-封装svg
  • 卷严重、难度高、激励少,如何适应空投市场新变化
  • 基于Java与JSP的文件上传和下载
  • Gromacs中的g_mmpbsa计算带电底物与蛋白的结合能不准确
  • 【mmrotate】旋转目标检测之训练DOTA数据集
  • 图基本概念
  • 机器学习基础
  • FreeRTOS-Tickless低功耗模式 | FreeRTOS十四
  • 实现了统一消息中心的微服务基础框架 JVS,快点赞收藏
  • VMware 安装 OpenWrt 旁路由并配置 PassWall
  • R语言GD包地理探测器分析时报错、得不到结果等情况的解决方案
  • 嵌入式开发:你需要知道的5种简单