### Configure Redis or ZooKeeper Backend Source: https://github.com/baomidou/lock4j/blob/master/README.md Configure your chosen backend (Redis or ZooKeeper) in your application's properties file. This setup is required for Lock4j to function with the selected executor. ```yaml spring: redis: host: 127.0.0.1 ... coordinate: zookeeper: zkServers: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183 ``` -------------------------------- ### Implement Custom Database Lock Executor Source: https://context7.com/baomidou/lock4j/llms.txt Extend AbstractLockExecutor to create a custom lock implementation, such as a database-based distributed lock. This example shows the basic structure for acquiring and releasing locks. ```java import com.baomidou.lock.executor.AbstractLockExecutor; import org.springframework.stereotype.Component; // 自定义锁执行器示例(基于数据库的分布式锁) @Component public class DatabaseLockExecutor extends AbstractLockExecutor { @Override public boolean renewal() { return false; // 数据库锁不支持自动续期 } @Override public String acquire(String lockKey, String lockValue, long expire, long acquireTimeout) { // 实现基于数据库的加锁逻辑 // 例如:INSERT INTO distributed_lock (lock_key, lock_value, expire_time) VALUES (?, ?, ?) try { boolean locked = tryAcquireDatabaseLock(lockKey, lockValue, expire); return obtainLockInstance(locked, lockValue); } catch (Exception e) { return null; } } @Override public boolean releaseLock(String key, String value, String lockInstance) { // 实现基于数据库的解锁逻辑 // 例如:DELETE FROM distributed_lock WHERE lock_key = ? AND lock_value = ? try { return releaseDatabaseLock(key, value); } catch (Exception e) { return false; } } private boolean tryAcquireDatabaseLock(String key, String value, long expire) { // 实际的数据库锁获取逻辑 return true; } private boolean releaseDatabaseLock(String key, String value) { // 实际的数据库锁释放逻辑 return true; } } ``` -------------------------------- ### Handle Lock Failure Exception Source: https://context7.com/baomidou/lock4j/llms.txt Lock4j throws LockFailureException when acquiring a lock fails. This example shows how to catch this exception globally using @RestControllerAdvice and within a controller. ```java import com.baomidou.lock.annotation.Lock4j; import com.baomidou.lock.exception.LockFailureException; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.*; @Service public class LockExceptionHandleService { @Lock4j(keys = {"#id"}, acquireTimeout = 1000, expire = 5000) public void processWithLock(String id) { System.out.println("处理业务: " + id); try { Thread.sleep(3000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } // 全局异常处理器 @RestControllerAdvice class GlobalExceptionHandler { @ExceptionHandler(LockFailureException.class) public String handleLockFailure(LockFailureException e) { // 返回友好的错误信息 return "操作太频繁,请稍后再试"; } } // Controller 示例 @RestController @RequestMapping("/api") class DemoController { private final LockExceptionHandleService service; public DemoController(LockExceptionHandleService service) { this.service = service; } @PostMapping("/process/{id}") public String process(@PathVariable String id) { try { service.processWithLock(id); return "处理成功"; } catch (LockFailureException e) { return "系统繁忙,请稍后再试"; } } } ``` -------------------------------- ### Enable Lock Auto-Renewal with RedisTemplate Source: https://context7.com/baomidou/lock4j/llms.txt Configure RedisTemplateLockExecutor to automatically renew locks by setting `expire` to -1. This is useful for long-running tasks to prevent premature lock expiration. The example demonstrates checking lock expiration times before and after renewal. ```java import com.baomidou.lock.annotation.Lock4j; import com.baomidou.lock.executor.RedisTemplateLockExecutor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; @Service public class RenewalLockService { @Autowired private StringRedisTemplate stringRedisTemplate; // 启用自动续期(expire = -1) @Lock4j( keys = "renewal_task", expire = -1, // 设置为-1启用自动续期 executor = RedisTemplateLockExecutor.class ) public void longRunningTaskWithRenewal() { System.out.println("开始长时间任务,锁会自动续期"); // 查看初始锁过期时间 Long initialExpire = stringRedisTemplate.getExpire( "lock4j:com.example.RenewalLockServicelongRunningTaskWithRenewal#renewal_task", TimeUnit.MILLISECONDS ); System.out.println("初始锁过期时间: " + initialExpire + "ms"); try { // 模拟超过默认过期时间的长任务 Thread.sleep(40000); // 40秒,超过默认30秒 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } // 查看续期后的过期时间 Long renewedExpire = stringRedisTemplate.getExpire( "lock4j:com.example.RenewalLockServicelongRunningTaskWithRenewal#renewal_task", TimeUnit.MILLISECONDS ); System.out.println("续期后锁过期时间: " + renewedExpire + "ms"); System.out.println("任务完成"); } } ``` -------------------------------- ### Global Configuration in application.yml Source: https://context7.com/baomidou/lock4j/llms.txt Configure global default parameters for Lock4j, including Redis and ZooKeeper connection details, lock timeouts, retry intervals, and key prefixes. ```yaml spring: redis: host: 127.0.0.1 port: 6379 password: your_password database: 0 coordinate: zookeeper: zkServers: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183 lock4j: acquire-timeout: 3000 # 获取锁超时时间,单位毫秒,默认3秒 expire: 30000 # 锁过期时间,单位毫秒,默认30秒 retry-interval: 100 # 获取锁失败时重试间隔,单位毫秒,默认100ms lock-key-prefix: lock4j # 锁key前缀,默认lock4j primary-executor: com.baomidou.lock.executor.RedissonLockExecutor # 默认执行器 ``` -------------------------------- ### Maven Dependencies for Lock4j Source: https://github.com/baomidou/lock4j/blob/master/README.md Include these dependencies in your pom.xml to use Lock4j with different backend implementations. Choose the starter corresponding to your desired lock executor. ```xml com.baomidou lock4j-redis-template-spring-boot-starter ${latest.version} com.baomidou lock4j-redisson-spring-boot-starter ${latest.version} com.baomidou lock4j-zookeeper-spring-boot-starter ${latest.version} ``` -------------------------------- ### Programmatic Lock Acquisition and Release Source: https://github.com/baomidou/lock4j/blob/master/README.md Use `LockTemplate` for manual control over lock acquisition and release. This is useful for complex scenarios where annotations are not sufficient. Ensure `LockTemplate` is injected. ```java @Service public class ProgrammaticService { @Autowired private LockTemplate lockTemplate; public void programmaticLock(String userId) { // Various query operations without locking // ... // Acquire lock final LockInfo lockInfo = lockTemplate.lock(userId, 30000L, 5000L, RedissonLockExecutor.class); if (null == lockInfo) { throw new RuntimeException("Processing in business, please try again later"); } // Lock acquired successfully, process business try { System.out.println("Execute simple method 1, current thread:" + Thread.currentThread().getName() + " , counter:" + (counter++)); } finally { // Release lock lockTemplate.releaseLock(lockInfo); } // End } } ``` -------------------------------- ### Custom Key Builder Implementation Source: https://context7.com/baomidou/lock4j/llms.txt Extend DefaultLockKeyBuilder to implement LockKeyBuilder for custom lock key generation. This allows for adding prefixes like tenant IDs or other contextual information to the lock keys. ```java import com.baomidou.lock.DefaultLockKeyBuilder; import com.baomidou.lock.LockKeyBuilder; import com.baomidou.lock.MethodBasedExpressionEvaluator; import com.baomidou.lock.annotation.Lock4j; import org.aopalliance.intercept.MethodInvocation; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; // 自定义 Key 生成器 @Component public class CustomLockKeyBuilder extends DefaultLockKeyBuilder { public CustomLockKeyBuilder(MethodBasedExpressionEvaluator methodBasedExpressionEvaluator) { super(methodBasedExpressionEvaluator); } @Override public String buildKey(MethodInvocation invocation, String[] definitionKeys) { // 获取默认生成的 key String key = super.buildKey(invocation, definitionKeys); // 添加自定义前缀(如租户ID) String tenantId = getTenantId(); // 返回格式: tenant:className:methodName:customKey return tenantId + ":" + invocation.getMethod().getDeclaringClass().getSimpleName() + ":" + invocation.getMethod().getName() + ":" + key; } private String getTenantId() { // 从上下文获取租户ID return "tenant_001"; } } ``` ```java // 使用自定义 Key 生成器 @Service public class TenantService { @Lock4j( keys = {"#resourceId"}, expire = 30000, keyBuilderStrategy = CustomLockKeyBuilder.class // 指定自定义 Key 生成器 ) public void processResource(String resourceId) { System.out.println("处理资源: " + resourceId); } } ``` -------------------------------- ### Rate Limiting with Lock4j (Auto Release Disabled) Source: https://github.com/baomidou/lock4j/blob/master/README.md Configure a lock with `autoRelease = false` to implement rate limiting. This prevents the lock from being automatically released, effectively limiting access to once within the specified `expire` duration. ```java @Service public class DemoService { // User can only access 1 time within 5 seconds @Lock4j(keys = {"#user.id"}, acquireTimeout = 0, expire = 5000, autoRelease = false) public Boolean test(User user) { return "true"; } } ``` -------------------------------- ### Custom Lock Key Builder Source: https://github.com/baomidou/lock4j/blob/master/README.md Extend `DefaultLockKeyBuilder` to create a custom lock key generator. Override the `buildKey` method to implement your custom logic for generating lock keys. ```java @Component public class MyLockKeyBuilder extends DefaultLockKeyBuilder { @Override public String buildKey(MethodInvocation invocation, String[] definitionKeys) { String key = super.buildKey(invocation, definitionKeys); // do something return key; } } ``` -------------------------------- ### Advanced @Lock4j Annotation Configuration Source: https://context7.com/baomidou/lock4j/llms.txt Configure advanced options for @Lock4j, including dynamic SpEL expressions for keys, custom expire times, acquire timeouts, and specifying the lock executor. ```java import com.baomidou.lock.annotation.Lock4j; import com.baomidou.lock.executor.RedissonLockExecutor; import org.springframework.stereotype.Service; @Service public class OrderService { // 完整配置:指定 key、过期时间、超时时间和执行器 @Lock4j( keys = {"#user.id", "#user.name"}, // SpEL 表达式,支持多个 key expire = 60000, // 锁过期时间60秒 acquireTimeout = 5000, // 获取锁超时时间5秒 executor = RedissonLockExecutor.class // 指定使用 Redisson 执行器 ) public User updateUser(User user) { System.out.println("更新用户: " + user.getId()); return user; } } ``` -------------------------------- ### Interface Rate Limiting with autoRelease=false Source: https://context7.com/baomidou/lock4j/llms.txt Configure interface rate limiting by setting autoRelease to false. The lock will not be automatically released after the method execution. ```java import com.baomidou.lock.annotation.Lock4j; import org.springframework.stereotype.Service; @Service public class RateLimitService { // 用户在5秒内只能访问1次(接口限流) @Lock4j( keys = {"#userId"}, acquireTimeout = 0, // 立即返回,不等待 expire = 5000, // 锁持续5秒 autoRelease = false // 方法执行完不自动释放锁 ) public String limitedApi(String userId) { return "用户 " + userId + " 请求成功"; } // 每个IP每分钟最多请求1次 @Lock4j( keys = {"#ip"}, acquireTimeout = 0, expire = 60000, // 锁持续60秒 autoRelease = false ) public String ipRateLimit(String ip) { return "IP " + ip + " 请求成功"; } // 支付接口防重复提交 @Lock4j( keys = {"'pay'", "#orderId"}, acquireTimeout = 0, expire = 30000, autoRelease = false ) public void payOrder(String orderId, java.math.BigDecimal amount) { System.out.println("处理支付订单: " + orderId + ", 金额: " + amount); // 实际支付逻辑 } } ``` -------------------------------- ### Configure Global Default Lock Settings Source: https://github.com/baomidou/lock4j/blob/master/README.md Set global default values for lock acquisition timeout and expiration time in your application properties. These defaults can be overridden at the method level. ```yaml lock4j: acquire-timeout: 3000 #Default value is 3s, can be omitted expire: 30000 #Default value is 30s, can be omitted primary-executor: com.baomidou.lock.executor.RedisTemplateLockExecutor #Default is redisson>redisTemplate>zookeeper, can be omitted lock-key-prefix: lock4j #Lock key prefix, default value is lock4j, can be omitted ``` -------------------------------- ### Basic @Lock4j Annotation Usage Source: https://context7.com/baomidou/lock4j/llms.txt Apply the @Lock4j annotation to a method to enable distributed locking with default configuration. This is suitable for basic resource protection. ```java import com.baomidou.lock.annotation.Lock4j; import org.springframework.stereotype.Service; @Service public class OrderService { // 基础用法:使用默认配置(获取锁超时3秒,锁过期30秒) @Lock4j public void createOrder() { // 业务逻辑 System.out.println("创建订单中..."); } } ``` -------------------------------- ### Global Lock with @Lock4j 'name' Parameter Source: https://context7.com/baomidou/lock4j/llms.txt Use the 'name' parameter in @Lock4j to create a global lock or resource lock that can be shared across multiple methods or services. ```java import com.baomidou.lock.annotation.Lock4j; import org.springframework.stereotype.Service; @Service public class OrderService { // 使用 name 参数实现全局锁或资源锁 @Lock4j( name = "global-inventory-lock", // 锁名称,多个方法可以共用同一把锁 keys = {"#productId"}, expire = 10000, acquireTimeout = 3000 ) public void decreaseInventory(String productId, int quantity) { System.out.println("扣减库存: " + productId + ", 数量: " + quantity); } } ``` -------------------------------- ### RedissonLock Annotation Basic Usage Source: https://context7.com/baomidou/lock4j/llms.txt Use the @RedissonLock annotation for basic distributed locking with Redisson. Specify keys, acquisition timeout, and expiration time. ```java import com.baomidou.lock.annotation.RedissonLock; import org.springframework.stereotype.Service; @Service public class RedissonLockService { // 基础用法 @RedissonLock( keys = {"#user.id", "#user.name"}, acquireTimeout = 5000, expire = 5000 ) public User processUser(User user) { System.out.println("处理用户: " + user.getId()); try { // 模拟业务处理 Thread.sleep(4000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return user; } // 启用自动续期(expire = -1) @RedissonLock( keys = {"#orderId"}, expire = -1, // 设置为-1启用自动续期 acquireTimeout = 3000 ) public void longRunningTask(String orderId) { System.out.println("开始长时间任务: " + orderId); try { // 长时间运行的任务,锁会自动续期 Thread.sleep(60000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println("任务完成: " + orderId); } } ``` -------------------------------- ### Multiple @Lock4j Annotations with Order Source: https://context7.com/baomidou/lock4j/llms.txt Apply multiple @Lock4j annotations to a single method to acquire multiple locks. The 'order' attribute controls the sequence in which locks are acquired. ```java import com.baomidou.lock.annotation.Lock4j; import com.baomidou.lock.DefaultLockFailureStrategy; import com.baomidou.lock.DefaultLockKeyBuilder; import org.springframework.stereotype.Service; @Service public class MultiLockService { // 根据条件动态选择加锁,order 越小越先执行 @Lock4j( condition = "#id % 2 == 0", // id为偶数时加锁 keys = "#id + '_even'", keyBuilderStrategy = DefaultLockKeyBuilder.class, failStrategy = DefaultLockFailureStrategy.class, order = 0 // 第一个执行 ) @Lock4j( condition = "#id % 4 == 0", // id为4的倍数时加锁 keys = "#id + '_quad'", keyBuilderStrategy = DefaultLockKeyBuilder.class, failStrategy = DefaultLockFailureStrategy.class, order = 1 // 第二个执行 ) @Lock4j( condition = "#id % 6 == 0", // id为6的倍数时加锁 keys = "#id + '_hex'", keyBuilderStrategy = DefaultLockKeyBuilder.class, failStrategy = DefaultLockFailureStrategy.class, order = 2 // 第三个执行 ) public void processWithMultiCondition(Integer id) { System.out.println("处理ID: " + id + ", 线程: " + Thread.currentThread().getName()); } } ``` -------------------------------- ### LockTemplate Programmatic Locking (Redisson) Source: https://context7.com/baomidou/lock4j/llms.txt Use LockTemplate for programmatic distributed locking with Redisson. Specify key, expiration, acquisition timeout, and executor class. ```java import com.baomidou.lock.LockInfo; import com.baomidou.lock.LockTemplate; import com.baomidou.lock.executor.RedissonLockExecutor; import com.baomidou.lock.executor.RedisTemplateLockExecutor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class ProgrammaticLockService { @Autowired private LockTemplate lockTemplate; // 基础编程式锁 public void simpleProcess(String userId) { // 获取锁:key, 过期时间(ms), 获取超时时间(ms), 执行器类型 LockInfo lockInfo = lockTemplate.lock(userId, 30000L, 5000L, RedissonLockExecutor.class); if (lockInfo == null) { throw new RuntimeException("业务处理中,请稍后再试"); } try { // 获取锁成功,执行业务逻辑 System.out.println("处理用户业务: " + userId); processBusinessLogic(userId); } finally { // 必须在 finally 中释放锁 lockTemplate.releaseLock(lockInfo); } } // 使用默认配置的简化版本 public void quickProcess(String resourceId) { LockInfo lockInfo = lockTemplate.lock(resourceId); // 使用默认配置 if (lockInfo == null) { throw new RuntimeException("获取锁失败"); } try { System.out.println("处理资源: " + resourceId); } finally { lockTemplate.releaseLock(lockInfo); } } // 使用 RedisTemplate 执行器 public void processWithRedisTemplate(String key) { LockInfo lockInfo = lockTemplate.lock(key, 60000L, 3000L, RedisTemplateLockExecutor.class); if (lockInfo == null) { System.out.println("获取锁失败,key: " + key); return; } try { System.out.println("锁信息 - Key: " + lockInfo.getLockKey()); System.out.println("锁信息 - Value: " + lockInfo.getLockValue()); System.out.println("锁信息 - 获取次数: " + lockInfo.getAcquireCount()); // 业务处理 Thread.sleep(5000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { boolean released = lockTemplate.releaseLock(lockInfo); System.out.println("锁释放结果: " + released); } } private void processBusinessLogic(String userId) { // 实际业务逻辑 } } ``` -------------------------------- ### Custom Lock Failure Strategy Implementation Source: https://context7.com/baomidou/lock4j/llms.txt Implement the LockFailureStrategy interface to define custom logic for handling lock acquisition failures. This allows for specific error messages or actions based on the method or arguments. ```java import com.baomidou.lock.LockFailureStrategy; import com.baomidou.lock.annotation.Lock4j; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import java.lang.reflect.Method; // 自定义锁失败策略 @Component public class CustomLockFailureStrategy implements LockFailureStrategy { @Override public void onLockFailure(String key, Method method, Object[] arguments) { // 记录日志 System.err.println("获取锁失败 - Key: " + key + ", Method: " + method.getName()); // 可以根据方法或参数返回不同的错误信息 if (method.getName().contains("payment")) { throw new RuntimeException("支付处理中,请勿重复提交"); } else if (method.getName().contains("order")) { throw new RuntimeException("订单处理中,请稍后再试"); } else { throw new RuntimeException("系统繁忙,请稍后重试"); } } } ``` ```java // 使用自定义失败策略 @Service public class PaymentService { @Lock4j( keys = {"#orderId"}, expire = 30000, acquireTimeout = 3000, failStrategy = CustomLockFailureStrategy.class // 指定自定义失败策略 ) public void processPayment(String orderId) { System.out.println("处理支付: " + orderId); } } ``` -------------------------------- ### LocalLock Annotation for Single-Node Source: https://context7.com/baomidou/lock4j/llms.txt Use the @LocalLock annotation for in-memory, single-node locking. Configure expiration and acquisition timeout. ```java import com.baomidou.lock.annotation.LocalLock; import org.springframework.stereotype.Service; @Service public class LocalLockService { // 本地锁,适用于单机环境 @LocalLock( keys = "inventory", expire = 5000, // 锁过期时间5秒 acquireTimeout = 1000 // 获取锁超时1秒 ) public void localProcess() { System.out.println("本地锁方法执行, 线程: " + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } ``` -------------------------------- ### Maven Dependencies for Lock4j Source: https://context7.com/baomidou/lock4j/llms.txt Include the appropriate Maven dependency based on your chosen distributed lock implementation (RedisTemplate, Redisson, or ZooKeeper). ```xml com.baomidou lock4j-redis-template-spring-boot-starter 2.2.7 ``` ```xml com.baomidou lock4j-redisson-spring-boot-starter 2.2.7 ``` ```xml com.baomidou lock4j-zookeeper-spring-boot-starter 2.2.7 ``` -------------------------------- ### Custom Lock Failure Strategy Source: https://github.com/baomidou/lock4j/blob/master/README.md Implement the `LockFailureStrategy` interface to define a custom strategy for handling lock acquisition failures. Register your custom strategy as a Spring bean. ```java @Component public class MyLockFailureStrategy implements LockFailureStrategy { @Override public void onLockFailure(String key, long acquireTimeout, int acquireCount) { // write my code } } ``` -------------------------------- ### Basic Lock4j Annotation Usage Source: https://github.com/baomidou/lock4j/blob/master/README.md Apply the @Lock4j annotation to methods that require distributed locking. By default, it acquires locks with a 3-second timeout and a 30-second expiration. ```java @Service public class DemoService { //Default lock acquisition timeout is 3 seconds, lock expiration is 30 seconds @Lock4j public void simple() { //do something } //Fully configured, supports spel @Lock4j(keys = {"#user.id", "#user.name"}, expire = 60000, acquireTimeout = 1000) public User customMethod(User user) { return user; } } ``` -------------------------------- ### Conditional Locking with @Lock4j 'condition' Parameter Source: https://context7.com/baomidou/lock4j/llms.txt Implement conditional locking using the 'condition' parameter in @Lock4j. The lock is only acquired if the specified SpEL expression evaluates to true. ```java import com.baomidou.lock.annotation.Lock4j; import org.springframework.stereotype.Service; @Service public class OrderService { // 条件锁:只有满足条件时才加锁 @Lock4j( condition = "#amount.compareTo(new java.math.BigDecimal('100')) > 0", // 金额大于100才加锁 keys = {"#orderId"}, expire = 30000 ) public void processPayment(String orderId, java.math.BigDecimal amount) { System.out.println("处理支付: " + orderId + ", 金额: " + amount); } } ``` -------------------------------- ### Specify Lock Executor in Method Source: https://github.com/baomidou/lock4j/blob/master/README.md You can specify a particular lock executor for a method using the `executor` attribute of the @Lock4j annotation. Ensure custom executors are registered as Spring beans. ```java @Service public class DemoService { //Can specify which executor to use at the method level, if you implement it yourself, you need to inject it into Spring in advance. @Lock4j(executor = RedissonLockExecutor.class) public Boolean test() { return "true"; } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.