马府强
2 years ago
22 changed files with 802 additions and 0 deletions
@ -0,0 +1,31 @@ |
|||
package org.example.sublist; |
|||
|
|||
|
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 数组测试 |
|||
* |
|||
* @author xiaomage |
|||
* @date 2022/12/25 |
|||
*/ |
|||
public class ArrayListTest { |
|||
|
|||
public static void main(String[] args) { |
|||
List<Integer> statusList = Arrays.asList(1, 2); |
|||
System.out.println(statusList); |
|||
System.out.println(statusList.contains(1)); |
|||
System.out.println(statusList.contains(3)); |
|||
|
|||
|
|||
statusList.add(3); |
|||
System.out.println(statusList.contains(3)); |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
} |
|||
|
|||
} |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,8 @@ |
|||
# Default ignored files |
|||
/shelf/ |
|||
/workspace.xml |
|||
# Datasource local storage ignored files |
|||
/../../../:\redislockdemo\.idea/dataSources/ |
|||
/dataSources.local.xml |
|||
# Editor-based HTTP Client requests |
|||
/httpRequests/ |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="CompilerConfiguration"> |
|||
<annotationProcessing> |
|||
<profile name="Maven default annotation processors profile" enabled="true"> |
|||
<sourceOutputDir name="target/generated-sources/annotations" /> |
|||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" /> |
|||
<outputRelativeToContentRoot value="true" /> |
|||
<module name="redislockdemo" /> |
|||
</profile> |
|||
</annotationProcessing> |
|||
</component> |
|||
</project> |
@ -0,0 +1,7 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="Encoding"> |
|||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" /> |
|||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" /> |
|||
</component> |
|||
</project> |
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="RemoteRepositoriesConfiguration"> |
|||
<remote-repository> |
|||
<option name="id" value="central" /> |
|||
<option name="name" value="Central Repository" /> |
|||
<option name="url" value="https://repo.maven.apache.org/maven2" /> |
|||
</remote-repository> |
|||
<remote-repository> |
|||
<option name="id" value="central" /> |
|||
<option name="name" value="Maven Central repository" /> |
|||
<option name="url" value="https://repo1.maven.org/maven2" /> |
|||
</remote-repository> |
|||
<remote-repository> |
|||
<option name="id" value="jboss.community" /> |
|||
<option name="name" value="JBoss Community repository" /> |
|||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" /> |
|||
</remote-repository> |
|||
</component> |
|||
</project> |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="ExternalStorageConfigurationManager" enabled="true" /> |
|||
<component name="MavenProjectsManager"> |
|||
<option name="originalFiles"> |
|||
<list> |
|||
<option value="$PROJECT_DIR$/pom.xml" /> |
|||
</list> |
|||
</option> |
|||
</component> |
|||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK"> |
|||
<output url="file://$PROJECT_DIR$/out" /> |
|||
</component> |
|||
</project> |
@ -0,0 +1,319 @@ |
|||
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<groupId>com.xiaomage</groupId> |
|||
<artifactId>redislockdemo</artifactId> |
|||
<version>1.0-SNAPSHOT</version> |
|||
|
|||
|
|||
<properties> |
|||
<!--版本号--> |
|||
<pangu.version>1.0.0</pangu.version> |
|||
<!--编码--> |
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
|||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
|||
<!--jdk版本--> |
|||
<java.version>1.8</java.version> |
|||
|
|||
<!--三方版本--> |
|||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> |
|||
<shiro.version>1.6.0</shiro.version> |
|||
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version> |
|||
<mybatis.boot.version>1.3.2</mybatis.boot.version> |
|||
<druid.version>1.1.22</druid.version> |
|||
<bitwalker.version>1.19</bitwalker.version> |
|||
<kaptcha.version>2.3.2</kaptcha.version> |
|||
<swagger.version>2.9.2</swagger.version> |
|||
<swagger-bootstrap-ui.version>1.8.9</swagger-bootstrap-ui.version> |
|||
<pagehelper.boot.version>1.2.5</pagehelper.boot.version> |
|||
<fastjson.version>1.2.73</fastjson.version> |
|||
<oshi.version>5.2.5</oshi.version> |
|||
<jna.version>5.5.0</jna.version> |
|||
<commons.io.version>2.5</commons.io.version> |
|||
<commons.fileupload.version>1.3.3</commons.fileupload.version> |
|||
<poi.version>3.17</poi.version> |
|||
<velocity.version>1.7</velocity.version> |
|||
<webmagic.version>0.7.3</webmagic.version> |
|||
<qiniu-java-sdk.version>[7.2.0, 7.2.99]</qiniu-java-sdk.version> |
|||
<bcprov-jdk15on.version>1.67</bcprov-jdk15on.version> |
|||
<gson.version>2.8.6</gson.version> |
|||
<spring-data-redis.version>2.1.3.RELEASE</spring-data-redis.version> |
|||
<netty-all.version>4.0.24.Final</netty-all.version> |
|||
<commons-pool2.version>2.9.0</commons-pool2.version> |
|||
<weixin-java.version>4.0.0</weixin-java.version> |
|||
|
|||
</properties> |
|||
|
|||
<dependencies> |
|||
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> |
|||
<dependency> |
|||
<groupId>org.springframework</groupId> |
|||
<artifactId>spring-context</artifactId> |
|||
<version>5.3.23</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.redisson</groupId> |
|||
<artifactId>redisson-spring-boot-starter</artifactId> |
|||
<version>3.14.1</version> |
|||
</dependency> |
|||
|
|||
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> |
|||
<dependency> |
|||
<groupId>org.springframework</groupId> |
|||
<artifactId>spring-aop</artifactId> |
|||
<version>5.3.22</version> |
|||
</dependency> |
|||
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> |
|||
|
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>fastjson</artifactId> |
|||
<version>1.2.73</version> |
|||
</dependency> |
|||
|
|||
|
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-aop</artifactId> |
|||
</dependency> |
|||
|
|||
<!--集成redis--> |
|||
<!--springboot中的redis依赖--> |
|||
<dependency> |
|||
<groupId>org.springframework.data</groupId> |
|||
<artifactId>spring-data-redis</artifactId> |
|||
<version>2.1.3.RELEASE</version> |
|||
</dependency> |
|||
|
|||
<!-- io常用工具类 --> |
|||
<dependency> |
|||
<groupId>commons-io</groupId> |
|||
<artifactId>commons-io</artifactId> |
|||
<version>2.5</version> |
|||
</dependency> |
|||
|
|||
<!--文件上传工具类 --> |
|||
<dependency> |
|||
<groupId>commons-fileupload</groupId> |
|||
<artifactId>commons-fileupload</artifactId> |
|||
<version>1.3.3</version> |
|||
</dependency> |
|||
|
|||
|
|||
|
|||
<!-- https://mvnrepository.com/artifact/junit/junit --> |
|||
<dependency> |
|||
<groupId>junit</groupId> |
|||
<artifactId>junit</artifactId> |
|||
<version>4.13</version> |
|||
<scope>test</scope> |
|||
</dependency> |
|||
|
|||
|
|||
<!--阿里数据库连接池 --> |
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>druid-spring-boot-starter</artifactId> |
|||
<version>${druid.version}</version> |
|||
</dependency> |
|||
|
|||
<!--验证码 --> |
|||
<dependency> |
|||
<groupId>com.github.penggle</groupId> |
|||
<artifactId>kaptcha</artifactId> |
|||
<version>${kaptcha.version}</version> |
|||
</dependency> |
|||
|
|||
<!--Shiro核心框架 --> |
|||
<dependency> |
|||
<groupId>org.apache.shiro</groupId> |
|||
<artifactId>shiro-core</artifactId> |
|||
<version>${shiro.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- Shiro使用Srping框架 --> |
|||
<dependency> |
|||
<groupId>org.apache.shiro</groupId> |
|||
<artifactId>shiro-spring</artifactId> |
|||
<version>${shiro.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- Shiro使用EhCache缓存框架 --> |
|||
<dependency> |
|||
<groupId>org.apache.shiro</groupId> |
|||
<artifactId>shiro-ehcache</artifactId> |
|||
<version>${shiro.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- thymeleaf模板引擎和shiro框架的整合 --> |
|||
<dependency> |
|||
<groupId>com.github.theborakompanioni</groupId> |
|||
<artifactId>thymeleaf-extras-shiro</artifactId> |
|||
<version>${thymeleaf.extras.shiro.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- SpringWeb模块 --> |
|||
<dependency> |
|||
<groupId>org.springframework</groupId> |
|||
<artifactId>spring-web</artifactId> |
|||
</dependency> |
|||
|
|||
<!--常用工具类 --> |
|||
<dependency> |
|||
<groupId>org.apache.commons</groupId> |
|||
<artifactId>commons-lang3</artifactId> |
|||
</dependency> |
|||
|
|||
|
|||
<!-- 解析客户端操作系统、浏览器等 --> |
|||
<dependency> |
|||
<groupId>eu.bitwalker</groupId> |
|||
<artifactId>UserAgentUtils</artifactId> |
|||
<version>${bitwalker.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- pagehelper 分页插件 --> |
|||
<dependency> |
|||
<groupId>com.github.pagehelper</groupId> |
|||
<artifactId>pagehelper-spring-boot-starter</artifactId> |
|||
<version>${pagehelper.boot.version}</version> |
|||
</dependency> |
|||
|
|||
<!--集成redis Lettuce --> |
|||
<!--springboot中的redis依赖--> |
|||
<dependency> |
|||
<groupId>org.springframework.data</groupId> |
|||
<artifactId>spring-data-redis</artifactId> |
|||
<version>${spring-data-redis.version}</version> |
|||
</dependency> |
|||
<!-- lettuce pool 缓存连接池--> |
|||
<dependency> |
|||
<groupId>org.apache.commons</groupId> |
|||
<artifactId>commons-pool2</artifactId> |
|||
<version>${commons-pool2.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>io.netty</groupId> |
|||
<artifactId>netty-all</artifactId> |
|||
<version>${netty-all.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 获取系统信息 --> |
|||
<dependency> |
|||
<groupId>com.github.oshi</groupId> |
|||
<artifactId>oshi-core</artifactId> |
|||
<version>${oshi.version}</version> |
|||
</dependency> |
|||
|
|||
|
|||
<!-- swagger2--> |
|||
<dependency> |
|||
<groupId>io.springfox</groupId> |
|||
<artifactId>springfox-swagger2</artifactId> |
|||
<version>${swagger.version}</version> |
|||
<exclusions> |
|||
<exclusion> |
|||
<groupId>io.swagger</groupId> |
|||
<artifactId>swagger-annotations</artifactId> |
|||
</exclusion> |
|||
<exclusion> |
|||
<groupId>io.swagger</groupId> |
|||
<artifactId>swagger-models</artifactId> |
|||
</exclusion> |
|||
</exclusions> |
|||
</dependency> |
|||
|
|||
<!-- swagger2-UI--> |
|||
<dependency> |
|||
<groupId>io.springfox</groupId> |
|||
<artifactId>springfox-swagger-ui</artifactId> |
|||
<version>${swagger.version}</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>com.github.xiaoymin</groupId> |
|||
<artifactId>swagger-bootstrap-ui</artifactId> |
|||
<version>${swagger-bootstrap-ui.version}</version> |
|||
</dependency> |
|||
|
|||
<!--io常用工具类 --> |
|||
<dependency> |
|||
<groupId>commons-io</groupId> |
|||
<artifactId>commons-io</artifactId> |
|||
<version>${commons.io.version}</version> |
|||
</dependency> |
|||
|
|||
<!--文件上传工具类 --> |
|||
<dependency> |
|||
<groupId>commons-fileupload</groupId> |
|||
<artifactId>commons-fileupload</artifactId> |
|||
<version>${commons.fileupload.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- excel工具 --> |
|||
<dependency> |
|||
<groupId>org.apache.poi</groupId> |
|||
<artifactId>poi-ooxml</artifactId> |
|||
<version>${poi.version}</version> |
|||
</dependency> |
|||
|
|||
<!--velocity代码生成使用模板 --> |
|||
<dependency> |
|||
<groupId>org.apache.velocity</groupId> |
|||
<artifactId>velocity</artifactId> |
|||
<version>${velocity.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 阿里JSON解析器 --> |
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>fastjson</artifactId> |
|||
<version>${fastjson.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- webmagic --> |
|||
<dependency> |
|||
<groupId>us.codecraft</groupId> |
|||
<artifactId>webmagic-core</artifactId> |
|||
<version>${webmagic.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>us.codecraft</groupId> |
|||
<artifactId>webmagic-extension</artifactId> |
|||
<version>${webmagic.version}</version> |
|||
</dependency> |
|||
|
|||
|
|||
|
|||
|
|||
<!-- gson --> |
|||
<dependency> |
|||
<groupId>com.google.code.gson</groupId> |
|||
<artifactId>gson</artifactId> |
|||
<version>${gson.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.projectlombok</groupId> |
|||
<artifactId>lombok</artifactId> |
|||
</dependency> |
|||
|
|||
</dependencies> |
|||
|
|||
<dependencyManagement> |
|||
<dependencies> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-dependencies</artifactId> |
|||
<version>2.1.17.RELEASE</version> |
|||
<type>pom</type> |
|||
<scope>import</scope> |
|||
</dependency> |
|||
</dependencies> |
|||
</dependencyManagement> |
|||
|
|||
|
|||
</project> |
@ -0,0 +1,2 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<module type="JAVA_MODULE" version="4" /> |
@ -0,0 +1,20 @@ |
|||
package com.xiaomage; |
|||
|
|||
import org.springframework.boot.SpringApplication; |
|||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
|||
|
|||
/** |
|||
* 主应用程序 |
|||
* |
|||
* @author Admin |
|||
* @date 2022/12/25 |
|||
*/ |
|||
@SpringBootApplication |
|||
public class MainApplication { |
|||
|
|||
public static void main(String[] args) { |
|||
SpringApplication.run(MainApplication.class, args); |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,25 @@ |
|||
package com.xiaomage.annotation; |
|||
|
|||
/** |
|||
* @className: Lock |
|||
* @author: xiaomage |
|||
* @date: 2022/12/25 |
|||
**/ |
|||
public @interface Lock { |
|||
|
|||
/** |
|||
* lock key |
|||
*/ |
|||
String value(); |
|||
|
|||
/** |
|||
* 锁超时时间,默认5000ms |
|||
*/ |
|||
long expireTime() default 5000L; |
|||
|
|||
/** |
|||
* 锁等待时间,默认50ms |
|||
*/ |
|||
long waitTime() default 50L; |
|||
|
|||
} |
@ -0,0 +1,100 @@ |
|||
package com.xiaomage.aop; |
|||
|
|||
|
|||
import com.xiaomage.annotation.Lock; |
|||
import com.xiaomage.service.LockManager; |
|||
import com.xiaomage.vo.LockResult; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.aspectj.lang.ProceedingJoinPoint; |
|||
import org.aspectj.lang.annotation.Around; |
|||
import org.aspectj.lang.annotation.Aspect; |
|||
import org.aspectj.lang.annotation.Pointcut; |
|||
import org.aspectj.lang.reflect.MethodSignature; |
|||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer; |
|||
import org.springframework.expression.EvaluationContext; |
|||
import org.springframework.expression.Expression; |
|||
import org.springframework.expression.ExpressionParser; |
|||
import org.springframework.expression.spel.standard.SpelExpressionParser; |
|||
import org.springframework.expression.spel.support.StandardEvaluationContext; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import javax.annotation.Resource; |
|||
import java.lang.reflect.Method; |
|||
|
|||
/** |
|||
* 锁注释解析器 |
|||
* |
|||
* @author Admin |
|||
* @date 2022/12/25 |
|||
*/ |
|||
|
|||
@Aspect |
|||
@Component |
|||
@Slf4j |
|||
public class LockAnnotationParser { |
|||
@Resource |
|||
private LockManager lockManager; |
|||
|
|||
/** |
|||
* 定义切点 |
|||
*/ |
|||
@Pointcut(value = "@annotation(com.xiaomage.annotation.Lock)") |
|||
private void cutMethod() { |
|||
} |
|||
|
|||
/** |
|||
* 切点逻辑具体实现 |
|||
*/ |
|||
@Around(value = "cutMethod() && @annotation(lock)") |
|||
public Object parser(ProceedingJoinPoint point, Lock lock) throws Throwable { |
|||
String value = lock.value(); |
|||
if (isEl(value)) { |
|||
value = getByEl(value, point); |
|||
} |
|||
LockResult lockResult = lockManager.lock(getRealLockKey(value), lock.expireTime(), lock.waitTime()); |
|||
try { |
|||
return point.proceed(); |
|||
} finally { |
|||
lockManager.unlock(lockResult.getRLock()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 解析 SpEL 表达式并返回其值 |
|||
*/ |
|||
private String getByEl(String el, ProceedingJoinPoint point) { |
|||
Method method = ((MethodSignature) point.getSignature()).getMethod(); |
|||
String[] paramNames = getParameterNames(method); |
|||
Object[] arguments = point.getArgs(); |
|||
|
|||
ExpressionParser parser = new SpelExpressionParser(); |
|||
Expression expression = parser.parseExpression(el); |
|||
EvaluationContext context = new StandardEvaluationContext(); |
|||
for (int i = 0; i < arguments.length; i++) { |
|||
context.setVariable(paramNames[i], arguments[i]); |
|||
} |
|||
|
|||
return expression.getValue(context, String.class); |
|||
} |
|||
|
|||
/** |
|||
* 获取方法参数名列表 |
|||
*/ |
|||
private String[] getParameterNames(Method method) { |
|||
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer(); |
|||
return u.getParameterNames(method); |
|||
} |
|||
|
|||
private boolean isEl(String str) { |
|||
return str.contains("#"); |
|||
} |
|||
|
|||
/** |
|||
* 锁键值 |
|||
*/ |
|||
private String getRealLockKey(String value) { |
|||
return String.format("lock:%s", value); |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,39 @@ |
|||
package com.xiaomage.configuration; |
|||
|
|||
|
|||
import org.redisson.Redisson; |
|||
import org.redisson.api.RedissonClient; |
|||
import org.redisson.config.Config; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.context.annotation.Bean; |
|||
|
|||
/** |
|||
* redisson配置 |
|||
* |
|||
* @author xiaomage |
|||
* @date 2022/12/25 |
|||
*/ |
|||
public class RedissonConfiguration { |
|||
|
|||
// 此处更换自己的 Redis 地址即可
|
|||
@Value("${redis.addr}") |
|||
private String addr; |
|||
|
|||
@Bean |
|||
public RedissonClient redisson() { |
|||
Config config = new Config(); |
|||
config.useSingleServer() |
|||
.setAddress(String.format("%s%s", "redis://", addr)) |
|||
.setConnectionPoolSize(64) // 连接池大小
|
|||
.setConnectionMinimumIdleSize(8) // 保持最小连接数
|
|||
.setConnectTimeout(1500) // 建立连接超时时间
|
|||
.setTimeout(2000) // 执行命令的超时时间, 从命令发送成功时开始计时
|
|||
.setRetryAttempts(2) // 命令执行失败重试次数
|
|||
.setRetryInterval(1000); // 命令重试发送时间间隔
|
|||
|
|||
return Redisson.create(config); |
|||
} |
|||
|
|||
|
|||
|
|||
} |
@ -0,0 +1,17 @@ |
|||
package com.xiaomage.entity; |
|||
|
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 学生 |
|||
* |
|||
* @author Admin |
|||
* @date 2022/12/25 |
|||
*/ |
|||
@Data |
|||
public class Student { |
|||
private String stuNo; |
|||
private String name; |
|||
|
|||
} |
@ -0,0 +1,22 @@ |
|||
package com.xiaomage.enu; |
|||
|
|||
/** |
|||
* @className: LockResultStatus |
|||
* @author: xiaomage |
|||
* @date: 2022/12/25 |
|||
**/ |
|||
public enum LockResultStatus { |
|||
|
|||
/** |
|||
* 通信正常,并且加锁成功 |
|||
*/ |
|||
SUCCESS, |
|||
/** |
|||
* 通信正常,但获取锁失败 |
|||
*/ |
|||
FAILURE, |
|||
/** |
|||
* 通信异常和内部异常,锁状态未知 |
|||
*/ |
|||
EXCEPTION; |
|||
} |
@ -0,0 +1,10 @@ |
|||
package com.xiaomage.enu; |
|||
|
|||
/** |
|||
* @className: ResponseEnum |
|||
* @author: Kevin |
|||
* @date: 2022/12/25 |
|||
**/ |
|||
public enum ResponseEnum { |
|||
COMMON_FREQUENT_OPERATION_ERROR |
|||
} |
@ -0,0 +1,6 @@ |
|||
package com.xiaomage.exception; |
|||
|
|||
public class BizException extends RuntimeException{ |
|||
public BizException(Object p0) { |
|||
} |
|||
} |
@ -0,0 +1,103 @@ |
|||
package com.xiaomage.service; |
|||
|
|||
|
|||
import com.xiaomage.enu.LockResultStatus; |
|||
import com.xiaomage.enu.ResponseEnum; |
|||
import com.xiaomage.exception.BizException; |
|||
import com.xiaomage.vo.LockResult; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.redisson.api.RLock; |
|||
import org.redisson.api.RedissonClient; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import javax.annotation.Resource; |
|||
import java.util.concurrent.TimeUnit; |
|||
import java.util.function.Supplier; |
|||
|
|||
/** |
|||
* 锁管理器 |
|||
* |
|||
* @author xiaomage |
|||
* @date 2022/12/25 |
|||
*/ |
|||
@Service |
|||
@Slf4j |
|||
public class LockManager { |
|||
|
|||
/** |
|||
* 最小锁等待时间 |
|||
*/ |
|||
private static final int MIN_WAIT_TIME = 10; |
|||
|
|||
@Resource |
|||
private RedissonClient redisson; |
|||
|
|||
/** |
|||
* 加锁,加锁失败抛默认异常 - 操作频繁, 请稍后再试 |
|||
* |
|||
* @param key 加锁唯一key |
|||
* @param expireTime 锁超时时间 毫秒 |
|||
* @param waitTime 加锁最长等待时间 毫秒 |
|||
* @return LockResult 加锁结果 |
|||
*/ |
|||
public LockResult lock(String key, long expireTime, long waitTime) { |
|||
return lock(key, expireTime, waitTime, () -> new BizException(ResponseEnum.COMMON_FREQUENT_OPERATION_ERROR)); |
|||
} |
|||
|
|||
/** |
|||
* 加锁,加锁失败抛异常 - 自定义异常 |
|||
* |
|||
* @param key 加锁唯一key |
|||
* @param expireTime 锁超时时间 毫秒 |
|||
* @param waitTime 加锁最长等待时间 毫秒 |
|||
* @param exceptionSupplier 加锁失败时抛该异常,传null时加锁失败不抛异常 |
|||
* @return LockResult 加锁结果 |
|||
*/ |
|||
private LockResult lock(String key, long expireTime, long waitTime, Supplier<BizException> exceptionSupplier) { |
|||
if (waitTime < MIN_WAIT_TIME) { |
|||
waitTime = MIN_WAIT_TIME; |
|||
} |
|||
|
|||
LockResult result = new LockResult(); |
|||
try { |
|||
RLock rLock = redisson.getLock(key); |
|||
try { |
|||
if (rLock.tryLock(waitTime, expireTime, TimeUnit.MILLISECONDS)) { |
|||
result.setLockResultStatus(LockResultStatus.SUCCESS); |
|||
result.setRLock(rLock); |
|||
} else { |
|||
result.setLockResultStatus(LockResultStatus.FAILURE); |
|||
} |
|||
} catch (InterruptedException e) { |
|||
log.error("Redis 获取分布式锁失败, key: {}, e: {}", key, e.getMessage()); |
|||
result.setLockResultStatus(LockResultStatus.EXCEPTION); |
|||
rLock.unlock(); |
|||
} |
|||
} catch (Exception e) { |
|||
log.error("Redis 获取分布式锁失败, key: {}, e: {}", key, e.getMessage()); |
|||
result.setLockResultStatus(LockResultStatus.EXCEPTION); |
|||
} |
|||
|
|||
if (exceptionSupplier != null && LockResultStatus.FAILURE.equals(result.getLockResultStatus())) { |
|||
log.warn("Redis 加锁失败, key: {}", key); |
|||
throw exceptionSupplier.get(); |
|||
} |
|||
|
|||
log.info("Redis 加锁结果:{}, key: {}", result.getLockResultStatus(), key); |
|||
|
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 解锁 |
|||
*/ |
|||
public void unlock(RLock rLock) { |
|||
try { |
|||
rLock.unlock(); |
|||
} catch (Exception e) { |
|||
log.warn("Redis 解锁失败", e); |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,27 @@ |
|||
package com.xiaomage.service; |
|||
|
|||
|
|||
import com.xiaomage.annotation.Lock; |
|||
import com.xiaomage.entity.Student; |
|||
import com.xiaomage.vo.LockResult; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import javax.annotation.Resource; |
|||
|
|||
@Service |
|||
@Slf4j |
|||
public class TestService { |
|||
|
|||
@Resource |
|||
private LockManager lockManager; |
|||
|
|||
|
|||
@Lock(value = "'test_'+#student.stuNo",expireTime = 3000, waitTime = 30) |
|||
public String test(Student student) { |
|||
// 业务代码
|
|||
return ""; |
|||
} |
|||
|
|||
|
|||
} |
@ -0,0 +1,16 @@ |
|||
package com.xiaomage.vo; |
|||
|
|||
|
|||
import com.xiaomage.enu.LockResultStatus; |
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
import org.redisson.api.RLock; |
|||
|
|||
@Setter |
|||
@Getter |
|||
public class LockResult { |
|||
|
|||
private LockResultStatus lockResultStatus; |
|||
|
|||
private RLock rLock; |
|||
} |
@ -0,0 +1,3 @@ |
|||
server.port= 8080 |
|||
|
|||
redis.addr = 192.168.56.10:6379 |
Loading…
Reference in new issue