原文网址:lock4j--分布式锁中间件--自定义获取锁失败的逻辑_IT利刃出鞘的博客-CSDN博客
说明
本文介绍lock4j如何自定义获取锁失败的逻辑。
概述
在注解模式下,对某个方法加锁,如果方法已上锁,默认抛出异常。默认的锁获取失败策略为 com.baomidou.lock.DefaultLockFailureStrategy 。
可以自定义处理方法,比如:如果方法上锁,其他线程执行时放弃执行,而不是抛异常。
相关网址
gitee:https://gitee.com/baomidou/lock4j
自定义获取锁失败逻辑:gitee官方测试用例
注意
本处使用lock4j过程中遇到了问题,不推荐使用lock4j,推荐直接使用redisson的分布式锁。
遇到的问题:
自定义实现类,实现LockFailureStrategy接口。
- import com.baomidou.lock.LockFailureStrategy;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Component;
-
- import java.lang.reflect.Method;
-
- /**
- * 自定义获取锁异常处理
- */
- @Slf4j
- @Component
- public class CustomLockFailureStrategy implements LockFailureStrategy {
-
- @Override
- public void onLockFailure(String key, Method method, Object[] arguments) {
- log.error("获取锁失败了,key={},method={},arguments={}", key, method, arguments);
- // 此处可以抛出指定异常,配合全局异常拦截包装统一格式返回给调用端
- throw new BusinessException("请求太快啦~");
- }
- }
默认的策略:DefaultLockFailureStrategy
- package com.baomidou.lock;
-
- import com.baomidou.lock.exception.LockFailureException;
- import lombok.extern.slf4j.Slf4j;
-
- import java.lang.reflect.Method;
-
- /**
- * @author zengzhihong
- */
- @Slf4j
- public class DefaultLockFailureStrategy implements LockFailureStrategy {
-
- protected static String DEFAULT_MESSAGE = "request failed,please retry it.";
-
- @Override
- public void onLockFailure(String key, Method method, Object[] arguments) {
- throw new LockFailureException(DEFAULT_MESSAGE);
- }
- }
- spring:
- redis:
- host: 192.168.5.193
- port: 6379
- password: 222333
-
- #lock4j:
- # acquire-timeout: 3000 #默认值3s,可不设置。排队时长,超过就退出排队,抛出获取锁超时异常。
- # expire: 30000 #默认值30s,可不设置
- # primary-executor: com.baomidou.lock.executor.RedissonLockExecutor #默认redisson > redisTemplate > zookeeper,可不设置
- # lock-key-prefix: lock4j #锁key前缀, 默认值lock4j,可不设置
- <!-- https://mvnrepository.com/artifact/com.baomidou/lock4j-redisson-spring-boot-starter -->
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
- <version>2.2.2</version>
- </dependency>
整个pom.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.4.13</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <groupId>com.knife.demo</groupId>
- <artifactId>demo_lock4j_SpringBoot</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>demo_lock4j_SpringBoot</name>
- <description>demo_lock4j_SpringBoot</description>
- <properties>
- <java.version>1.8</java.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <!-- https://mvnrepository.com/artifact/com.baomidou/lock4j-redisson-spring-boot-starter -->
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>lock4j-redisson-spring-boot-starter</artifactId>
- <version>2.2.2</version>
- </dependency>
-
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
-
- <dependency>
- <groupId>com.github.xiaoymin</groupId>
- <artifactId>knife4j-spring-boot-starter</artifactId>
- <version>3.0.3</version>
- </dependency>
-
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <configuration>
- <excludes>
- <exclude>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- </exclude>
- </excludes>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
- </project>
Controller
- package com.knife.demo.controller;
-
- import com.baomidou.lock.annotation.Lock4j;
- import com.knife.demo.entity.User;
- import io.swagger.annotations.Api;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- import java.util.ArrayList;
- import java.util.List;
-
- @Api(tags = "用户")
- @Slf4j
- @RestController
- @RequestMapping("user")
- public class UserController {
- @GetMapping("listAll")
- @Lock4j
- public List<User> listAllUser() {
- try {
- log.info("获取到锁,开始睡眠");
- Thread.sleep(15000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- return new ArrayList<>();
- }
-
- @GetMapping("find")
- @Lock4j(keys = {"#user.id", "#user.name"}, expire = 60000, acquireTimeout = 1000)
- public List<User> find(User user) {
- return new ArrayList<>();
- }
- }
Entity
- package com.knife.demo.entity;
-
- import lombok.Data;
-
- @Data
- public class User {
- private Long id;
-
- private String name;
- }
短时间内访问两次这个接口:http://localhost:8080/user/listAll

可以看到:获取锁超时时并没有抛异常,而是一直等待获取到锁。
后端结果

自定义策略
- package com.knife.demo.config;
-
- import com.baomidou.lock.LockFailureStrategy;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Component;
-
- import java.lang.reflect.Method;
-
- @Slf4j
- @Component
- public class CustomLockFailureStrategy implements LockFailureStrategy {
-
- @Override
- public void onLockFailure(String key, Method method, Object[] arguments) {
- log.error("获取锁失败了。key={},method={},arguments={}", key, method, arguments);
-
- // 此处可以抛出指定异常,配合全局异常拦截包装统一格式返回给调用端
- throw new RuntimeException("请求太快啦~");
- }
- }
短时间内访问两次这个接口:http://localhost:8080/user/listAll
结果:获取锁超时时并没有抛异常,而是一直等待获取到锁。

后端结果:
