通过Idea新建一个Gradle项目
配置Spring Boot的Gradle信息
配置插件信息
plugins {
id 'java-gradle-plugin'
id 'maven-publish'
id 'com.gradle.plugin-publish' version '0.12.0'
}
配置发布信息
group = 'com.springboot.starter.demo'
version = '1.0-SNAPSHOT'
publishing {
repositories {
maven {
url "https://mirrors.cloud.tencent.com/nexus/repository/maven-public/"
}
}
}
配置仓库信息
repositories {
mavenLocal()
maven {
url "https://mirrors.cloud.tencent.com/nexus/repository/maven-public/"
}
}
配置依赖的jar包信息
dependencies {
ext {
springBootVersion = "2.3.7.RELEASE"
}
implementation "org.springframework.boot:spring-boot-autoconfigure:${springBootVersion}"
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor:${springBootVersion}"
compileOnly "org.springframework.boot:spring-boot-starter-web:${springBootVersion}"
compileOnly "org.springframework.boot:spring-boot-starter-aop:${springBootVersion}"
implementation 'org.redisson:redisson:3.15.2'
// lombok
compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
}
compileJava.dependsOn(processResources)
开始Starter编写
定义一个句解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface EnableRedissonLock {
int waitTime() default 0;//等待时间
TimeUnit timeUnit() default TimeUnit.SECONDS;//时间单位
int leaseTime() default 3;//锁定时间
}
定义一个切面
@Aspect
@ConditionalOnWebApplication
@Slf4j
public class RedissonLockAspect {
private RedissonProvider redissonProvider;
public RedissonLockAspect(RedissonProvider redissonProvider) {
this.redissonProvider = redissonProvider;
}
@Around(value = "@annotation(com.springboot.redisson.starter.annotation.EnableRedissonLock)")
public Object handleRedisLock(ProceedingJoinPoint joinPoint) throws Throwable, Exception {
Object obj = null;
EnableRedissonLock enableRedisLock = ((MethodSignature) joinPoint.getSignature())
.getMethod()
.getAnnotation(EnableRedissonLock.class);
Object[] args = joinPoint.getArgs();
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String uri = request.getRequestURI();
String method = request.getMethod();
String userId = request.getHeader("USER-ID");
String params = Objects.nonNull(request.getParameterMap()) ? request.getParameterMap().toString() : "";
StringBuilder lockKey = new StringBuilder();
lockKey.append(uri)
.append("_")
.append(method)
.append("_")
.append(userId)
.append("_")
.append(params);
int waitTime = enableRedisLock.waitTime();
TimeUnit timeUnit = enableRedisLock.timeUnit();
int leaseTime = enableRedisLock.leaseTime();
log.debug("handleRedissonLock lockKey={}", lockKey.toString());
try {
if (redissonProvider.tryLock(lockKey.toString(), timeUnit, waitTime, leaseTime)) {
log.debug("handleRedissonLock lock success");
obj = joinPoint.proceed(args);
redissonProvider.unlock(lockKey.toString());
return obj;
} else {
log.debug("handleRedissonLock lock failure");
Map<String, String> map = new HashMap<>();
map.put("error", "请求太频繁");
ResponseUtil response = new ResponseUtil(905, map, null);
return response;
}
} catch (Exception ex){
redissonProvider.unlock(lockKey.toString());
throw ex;
}
}
}
定义redisson属性相关配置
@Data
@ConfigurationProperties(prefix = "redisson.starter")
public class RedissonProperties {
private String host;
private Integer port;
private String prefix = "redisson_starter_";
private String password;
}
定义redisson 实现类
@Slf4j
@ConditionalOnClass(Redisson.class)
public class RedissonProvider {
private RedissonClient redissonClient;
private String prefix;
public RedissonProvider(RedissonClient redissonClient, String prefix) {
this.redissonClient = redissonClient;
this.prefix = prefix;
}
public RLock lock(String lockKey) {
lockKey = prefix + lockKey;
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
public RLock lock(String lockKey, int leaseTime) {
lockKey = prefix + lockKey;
RLock lock = redissonClient.getLock(lockKey);
lock.lock(leaseTime, TimeUnit.SECONDS);
return lock;
}
public RLock lock(String lockKey, TimeUnit unit ,int timeout) {
lockKey = prefix + lockKey;
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
public void unlock(String lockKey) {
try {
lockKey = prefix + lockKey;
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
} catch (Exception ex) {
}
}
public void unlock(RLock lock) {
lock.unlock();
}
public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
lockKey = prefix + lockKey;
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
}
}
定义自动配置信息
@Configuration
@ConditionalOnProperty(prefix = "redisson.starter", name = "enabled", havingValue = "true")
@EnableConfigurationProperties(RedissonProperties.class)
@Import({RedissonLockAspect.class})
public class RedissonConfiguration {
@Resource
private RedissonProperties redissonProperties;
@Bean
public RedissonProvider redissonProvider() {
Config config = new Config();
String redisUrl = String.format("redis://%s:%s", redissonProperties.getHost()+"", redissonProperties.getPort()+"");
if(StringUtils.isNotEmpty(redissonProperties.getPassword())) {
config.useSingleServer()
.setAddress(redisUrl)
.setPassword(redissonProperties.getPassword())
.setTimeout(3000)
.setConnectionMinimumIdleSize(2)
.setConnectionPoolSize(32);
} else {
config.useSingleServer()
.setAddress(redisUrl)
.setTimeout(3000)
.setConnectionMinimumIdleSize(2)
.setConnectionPoolSize(32);
}
return new RedissonProvider(Redisson.create(config), redissonProperties.getPrefix());
}
}
配置EnableAutoConfiguration信息
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
net.coding.testing.base.spring.boot.starter.autoconfigure.RedissonConfiguration
具体源码地址:springboot-redisson-starter