Springboot2本地锁实践详解编程语言
编程语言 详解 实践 本地 SpringBoot2
2023-06-13 09:11:47 时间
在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交….
下面我们利用自定义注解、Spring Aop、Guava Cache 实现表单防重复提交
一、导入依赖创建springboot项目,在pom.xml文件中加入以下内容
dependencies dependency groupId org.springframework.boot /groupId artifactId spring-boot-starter-web /artifactId /dependency dependency groupId org.springframework.boot /groupId artifactId spring-boot-starter-aop /artifactId /dependency dependency groupId com.google.guava /groupId artifactId guava /artifactId version 21.0 /version /dependency /dependencies二、Lock注解
创建一个 LocalLock 注解,就一个 key 可以了
package com.carry.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 锁的注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface LocalLock { String key() default ""; }三、Lock拦截器(AOP)
首先通过 CacheBuilder.newBuilder() 构建出缓存对象,设置好过期时间;其目的就是为了防止因程序崩溃锁得不到释放,然后在具体的 interceptor() 方法上采用的是 Around(环绕增强) ,所有带 LocalLock 注解的都将被切面处理
具体代码
package com.carry.interceptor; import java.lang.reflect.Method; import java.util.concurrent.TimeUnit; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; import com.carry.annotation.LocalLock; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; @Aspect @Configuration public class LockMethodInterceptor { private static final Cache String, Object CACHES = CacheBuilder.newBuilder() // 最大缓存 100 个 .maximumSize(100) // 设置写缓存后 5 秒钟过期 .expireAfterWrite(5, TimeUnit.SECONDS).build(); @Around("execution(public * *(..)) @annotation(com.carry.annotation.LocalLock)") public Object interceptor(ProceedingJoinPoint pjp) { MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); LocalLock localLock = method.getAnnotation(LocalLock.class); String key = getKey(localLock.key(), pjp.getArgs()); if (!StringUtils.isEmpty(key)) { if (CACHES.getIfPresent(key) != null) { throw new RuntimeException("请勿重复请求"); // 如果是第一次请求,就将 key 当前对象压入缓存中 CACHES.put(key, key); try { return pjp.proceed(); } catch (Throwable throwable) { throw new RuntimeException("服务器异常"); } finally { // TODO /** * key 的生成策略,如果想灵活可以写成接口与实现类的方式 * @param keyExpress * 表达式 * @param args * 参数 * @return 生成的key private String getKey(String keyExpress, Object[] args) { for (int i = 0; i args.length; i++) { keyExpress = keyExpress.replace("arg[" + i + "]", args[i].toString()); return keyExpress; }四、控制层
在接口方法上添加 @LocalLock(key = "book:arg[0]");意味着会将 arg[0] 替换成第一个参数的值,生成后的新 key 将被缓存起来
具体代码
package com.carry.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.carry.annotation.LocalLock; @RestController @RequestMapping("/test") public class LocalLockController { @LocalLock(key = "key:arg[0]") @GetMapping public String query(@RequestParam String token) { return "success - " + token; }
启动项目,在postman中输入url:localhost:8080/test?token=1
第一次请求结果:
第二次请求结果:
17000.html
cgojavaxml相关文章
- Java8中Map的遍历方式总结详解编程语言
- Java 反射机制应用实践详解编程语言
- JavaMyBatis框架初步学习总结详解编程语言
- python获取本机网卡的mac地址详解编程语言
- JavaScript SHA512加密算法详细代码详解编程语言
- java使用poi读取excel文件代码示例详解编程语言
- 希尔排序 java 实现详解编程语言
- Java使用正则表达式搜索文本内所有的email地址并打印出来详解编程语言
- java计算指定日期的农历代码详解编程语言
- JSP连接DB2数据库详解编程语言
- SpringBoot之Filter And Listener(D)详解编程语言
- javaweb学习总结(三十)——EL函数库详解编程语言
- app微信支付宝支付后台的插件模式+回调通过spring广播处理后续业务(已亲测可用)详解编程语言
- Java学习笔记之三十详解Java单例(Singleton)模式编程语言
- [PHP] 试题系统研究详解编程语言
- Scala高阶函数实践详解编程语言
- JavaScript入门详解编程语言
- Java Exception处理之最佳实践详解编程语言
- 必须知道的八大种排序算法【java实现】(一) 冒泡排序、快速排序详解编程语言
- ASP.NET 使用Ajax详解编程语言
- javascript中两种基本常用排序算法分析详解编程语言
- Spring Boot 2 (五):Docker Compose + Spring Boot + Nginx + Mysql 实践详解编程语言
- java MessageFormat.format 用法详解编程语言
- java 监听文件或文件夹变化详解编程语言
- Myeclipse6.5每次打开properties中文注释都会变成乱码详解编程语言
- Python服务端面试—Mysql基础考点详解编程语言
- VA01复制单据,更新定价日期和价格详解编程语言
- PHP创建文件命名中文乱码解决的方法详解编程语言
- SAP ALV demo—自用详解编程语言
- BINARY SEARCH 的一点说明详解编程语言
- ABAP程序知识点详解编程语言