mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-01-03 12:05:28 +08:00
JeecgBoot2.4.3版本发布——企业级低代码平台
This commit is contained in:
@ -14,7 +14,7 @@ import java.lang.annotation.*;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface DistributedLock {
|
||||
public @interface JLock {
|
||||
|
||||
/**
|
||||
* 锁的模式:如果不设置,自动模式,当参数只有一个.使用 REENTRANT 参数多个 MULTIPLE
|
||||
@ -28,8 +28,7 @@ public @interface DistributedLock {
|
||||
String[] lockKey() default {};
|
||||
|
||||
/**
|
||||
* key的静态常量:当key的spel的值是LIST,数组时使用+号连接将会被spel认为这个变量是个字符串,只能产生一把锁,达不到我们的目的,<br />
|
||||
* 而我们如果又需要一个常量的话.这个参数将会在拼接在每个元素的后面
|
||||
* key的静态常量:当key的spel的值是LIST,数组时使用+号连接将会被spel认为这个变量是个字符串
|
||||
* @return
|
||||
*/
|
||||
String keyConstant() default "";
|
||||
@ -0,0 +1,36 @@
|
||||
package org.jeecg.boot.starter.lock.annotation;
|
||||
|
||||
/**
|
||||
* @author zyf
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 防止重复提交的注解
|
||||
*
|
||||
* @author 2019年6月18日
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
@Documented
|
||||
public @interface JRepeat {
|
||||
|
||||
/**
|
||||
* 超时时间
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int lockTime();
|
||||
|
||||
|
||||
/**
|
||||
* redis 锁key的
|
||||
*
|
||||
* @return redis 锁key
|
||||
*/
|
||||
String lockKey() default "";
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package org.jeecg.boot.starter.lock.annotation;
|
||||
|
||||
/**
|
||||
* @author zyf
|
||||
* @date 2019/10/26 18:26
|
||||
*/
|
||||
|
||||
/**
|
||||
* 分布式锁枚举类
|
||||
* @author zyf
|
||||
*/
|
||||
public enum LockConstant {
|
||||
/**
|
||||
* 通用锁常量
|
||||
*/
|
||||
COMMON("commonLock:", 1, 500, "请勿重复点击");
|
||||
/**
|
||||
* 分布式锁前缀
|
||||
*/
|
||||
private String keyPrefix;
|
||||
/**
|
||||
* 等到最大时间,强制获取锁
|
||||
*/
|
||||
private int waitTime;
|
||||
/**
|
||||
* 锁失效时间
|
||||
*/
|
||||
private int leaseTime;
|
||||
/**
|
||||
* 加锁提示
|
||||
*/
|
||||
private String message;
|
||||
|
||||
LockConstant(String keyPrefix, int waitTime, int leaseTime, String message) {
|
||||
this.keyPrefix = keyPrefix;
|
||||
this.waitTime = waitTime;
|
||||
this.leaseTime = leaseTime;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getKeyPrefix() {
|
||||
return keyPrefix;
|
||||
}
|
||||
|
||||
public void setKeyPrefix(String keyPrefix) {
|
||||
this.keyPrefix = keyPrefix;
|
||||
}
|
||||
|
||||
public int getWaitTime() {
|
||||
return waitTime;
|
||||
}
|
||||
|
||||
public void setWaitTime(int waitTime) {
|
||||
this.waitTime = waitTime;
|
||||
}
|
||||
|
||||
public int getLeaseTime() {
|
||||
return leaseTime;
|
||||
}
|
||||
|
||||
public void setLeaseTime(int leaseTime) {
|
||||
this.leaseTime = leaseTime;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
package org.jeecg.boot.starter.lock.aspect;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author zyf
|
||||
*/
|
||||
@Slf4j
|
||||
public class BaseAspect {
|
||||
|
||||
/**
|
||||
* 通过spring SpEL 获取参数
|
||||
*
|
||||
* @param key 定义的key值 以#开头 例如:#user
|
||||
* @param parameterNames 形参
|
||||
* @param values 形参值
|
||||
* @param keyConstant key的常亮
|
||||
* @return
|
||||
*/
|
||||
public List<String> getValueBySpEL(String key, String[] parameterNames, Object[] values, String keyConstant) {
|
||||
List<String> keys = new ArrayList<>();
|
||||
if (!key.contains("#")) {
|
||||
String s = "redis:lock:" + key + keyConstant;
|
||||
log.info("lockKey:" + s);
|
||||
keys.add(s);
|
||||
return keys;
|
||||
}
|
||||
//spel解析器
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
//spel上下文
|
||||
EvaluationContext context = new StandardEvaluationContext();
|
||||
for (int i = 0; i < parameterNames.length; i++) {
|
||||
context.setVariable(parameterNames[i], values[i]);
|
||||
}
|
||||
Expression expression = parser.parseExpression(key);
|
||||
Object value = expression.getValue(context);
|
||||
if (value != null) {
|
||||
if (value instanceof List) {
|
||||
List value1 = (List) value;
|
||||
for (Object o : value1) {
|
||||
addKeys(keys, o, keyConstant);
|
||||
}
|
||||
} else if (value.getClass().isArray()) {
|
||||
Object[] obj = (Object[]) value;
|
||||
for (Object o : obj) {
|
||||
addKeys(keys, o, keyConstant);
|
||||
}
|
||||
} else {
|
||||
addKeys(keys, value, keyConstant);
|
||||
}
|
||||
}
|
||||
log.info("表达式key={},value={}", key, keys);
|
||||
return keys;
|
||||
}
|
||||
|
||||
private void addKeys(List<String> keys, Object o, String keyConstant) {
|
||||
keys.add("redis:lock:" + o.toString() + keyConstant);
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ 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.jeecg.boot.starter.lock.annotation.DistributedLock;
|
||||
import org.jeecg.boot.starter.lock.annotation.JLock;
|
||||
import org.jeecg.boot.starter.lock.enums.LockModel;
|
||||
import org.redisson.RedissonMultiLock;
|
||||
import org.redisson.RedissonRedLock;
|
||||
@ -35,7 +35,7 @@ import java.util.concurrent.TimeUnit;
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@Component
|
||||
public class DistributedLockHandler {
|
||||
public class DistributedLockHandler extends BaseAspect{
|
||||
|
||||
|
||||
@Autowired(required = false)
|
||||
@ -45,20 +45,20 @@ public class DistributedLockHandler {
|
||||
* 切面环绕通知
|
||||
*
|
||||
* @param joinPoint
|
||||
* @param distributedLock
|
||||
* @param jLock
|
||||
* @return Object
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Around("@annotation(distributedLock)")
|
||||
public Object around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) {
|
||||
@Around("@annotation(jLock)")
|
||||
public Object around(ProceedingJoinPoint joinPoint, JLock jLock) {
|
||||
Object obj = null;
|
||||
log.info("进入RedisLock环绕通知...");
|
||||
RLock rLock = getLock(joinPoint, distributedLock);
|
||||
RLock rLock = getLock(joinPoint, jLock);
|
||||
boolean res = false;
|
||||
//获取超时时间
|
||||
long expireSeconds = distributedLock.expireSeconds();
|
||||
long expireSeconds = jLock.expireSeconds();
|
||||
//等待多久,n秒内获取不到锁,则直接返回
|
||||
long waitTime = distributedLock.waitTime();
|
||||
long waitTime = jLock.waitTime();
|
||||
//执行aop
|
||||
if (rLock != null) {
|
||||
try {
|
||||
@ -85,20 +85,20 @@ public class DistributedLockHandler {
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private RLock getLock(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) {
|
||||
String[] keys = distributedLock.lockKey();
|
||||
private RLock getLock(ProceedingJoinPoint joinPoint, JLock jLock) {
|
||||
String[] keys = jLock.lockKey();
|
||||
if (keys.length == 0) {
|
||||
throw new RuntimeException("keys不能为空");
|
||||
}
|
||||
String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(((MethodSignature) joinPoint.getSignature()).getMethod());
|
||||
Object[] args = joinPoint.getArgs();
|
||||
|
||||
LockModel lockModel = distributedLock.lockModel();
|
||||
LockModel lockModel = jLock.lockModel();
|
||||
if (!lockModel.equals(LockModel.MULTIPLE) && !lockModel.equals(LockModel.REDLOCK) && keys.length > 1) {
|
||||
throw new RuntimeException("参数有多个,锁模式为->" + lockModel.name() + ".无法锁定");
|
||||
}
|
||||
RLock rLock = null;
|
||||
String keyConstant = distributedLock.keyConstant();
|
||||
String keyConstant = jLock.keyConstant();
|
||||
if (lockModel.equals(LockModel.AUTO)) {
|
||||
if (keys.length > 1) {
|
||||
lockModel = LockModel.REDLOCK;
|
||||
@ -162,57 +162,6 @@ public class DistributedLockHandler {
|
||||
rLock = redissonClient.getReadWriteLock(getValueBySpEL(keys[0], parameterNames, args, keyConstant).get(0)).writeLock();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return rLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过spring SpEL 获取参数
|
||||
*
|
||||
* @param key 定义的key值 以#开头 例如:#user
|
||||
* @param parameterNames 形参
|
||||
* @param values 形参值
|
||||
* @param keyConstant key的常亮
|
||||
* @return
|
||||
*/
|
||||
public List<String> getValueBySpEL(String key, String[] parameterNames, Object[] values, String keyConstant) {
|
||||
List<String> keys = new ArrayList<>();
|
||||
if (!key.contains("#")) {
|
||||
String s = "redis:lock:" + key + keyConstant;
|
||||
log.info("lockKey:" + s);
|
||||
keys.add(s);
|
||||
return keys;
|
||||
}
|
||||
//spel解析器
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
//spel上下文
|
||||
EvaluationContext context = new StandardEvaluationContext();
|
||||
for (int i = 0; i < parameterNames.length; i++) {
|
||||
context.setVariable(parameterNames[i], values[i]);
|
||||
}
|
||||
Expression expression = parser.parseExpression(key);
|
||||
Object value = expression.getValue(context);
|
||||
if (value != null) {
|
||||
if (value instanceof List) {
|
||||
List value1 = (List) value;
|
||||
for (Object o : value1) {
|
||||
addKeys(keys, o, keyConstant);
|
||||
}
|
||||
} else if (value.getClass().isArray()) {
|
||||
Object[] obj = (Object[]) value;
|
||||
for (Object o : obj) {
|
||||
addKeys(keys, o, keyConstant);
|
||||
}
|
||||
} else {
|
||||
addKeys(keys, value, keyConstant);
|
||||
}
|
||||
}
|
||||
log.info("表达式key={},value={}", key, keys);
|
||||
return keys;
|
||||
}
|
||||
|
||||
private void addKeys(List<String> keys, Object o, String keyConstant) {
|
||||
keys.add("redis:lock:" + o.toString() + keyConstant);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
package org.jeecg.boot.starter.lock.aspect;
|
||||
|
||||
/**
|
||||
* @author zyf
|
||||
*/
|
||||
|
||||
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.jeecg.boot.starter.lock.annotation.JRepeat;
|
||||
import org.jeecg.boot.starter.lock.client.RedissonLockClient;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 防止重复提交分布式锁拦截器
|
||||
*
|
||||
* @author 2019年6月18日
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
public class RepeatSubmitAspect extends BaseAspect{
|
||||
|
||||
@Resource
|
||||
private RedissonLockClient redissonLockClient;
|
||||
|
||||
/***
|
||||
* 定义controller切入点拦截规则,拦截JRepeat注解的业务方法
|
||||
*/
|
||||
@Pointcut("@annotation(jRepeat)")
|
||||
public void pointCut(JRepeat jRepeat) {
|
||||
}
|
||||
|
||||
/**
|
||||
* AOP分布式锁拦截
|
||||
*
|
||||
* @param joinPoint
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Around("pointCut(jRepeat)")
|
||||
public Object repeatSubmit(ProceedingJoinPoint joinPoint,JRepeat jRepeat) throws Throwable {
|
||||
String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(((MethodSignature) joinPoint.getSignature()).getMethod());
|
||||
if (Objects.nonNull(jRepeat)) {
|
||||
// 获取参数
|
||||
Object[] args = joinPoint.getArgs();
|
||||
// 进行一些参数的处理,比如获取订单号,操作人id等
|
||||
StringBuffer lockKeyBuffer = new StringBuffer();
|
||||
String key =getValueBySpEL(jRepeat.lockKey(), parameterNames, args,"RepeatSubmit").get(0);
|
||||
// 公平加锁,lockTime后锁自动释放
|
||||
boolean isLocked = false;
|
||||
try {
|
||||
isLocked = redissonLockClient.fairLock(key, TimeUnit.SECONDS, jRepeat.lockTime());
|
||||
// 如果成功获取到锁就继续执行
|
||||
if (isLocked) {
|
||||
// 执行进程
|
||||
return joinPoint.proceed();
|
||||
} else {
|
||||
// 未获取到锁
|
||||
throw new Exception("请勿重复提交");
|
||||
}
|
||||
} finally {
|
||||
// 如果锁还存在,在方法执行完成后,释放锁
|
||||
if (isLocked) {
|
||||
redissonLockClient.unlock(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -21,6 +22,9 @@ public class RedissonLockClient {
|
||||
@Autowired
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
/**
|
||||
* 获取锁
|
||||
*/
|
||||
@ -60,6 +64,25 @@ public class RedissonLockClient {
|
||||
return getLock;
|
||||
}
|
||||
|
||||
|
||||
public boolean fairLock(String lockKey, TimeUnit unit, int leaseTime) {
|
||||
RLock fairLock = redissonClient.getFairLock(lockKey);
|
||||
try {
|
||||
boolean existKey = existKey(lockKey);
|
||||
// 已经存在了,就直接返回
|
||||
if (existKey) {
|
||||
return false;
|
||||
}
|
||||
return fairLock.tryLock(3, leaseTime, unit);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean existKey(String key) {
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
/**
|
||||
* 锁lockKey
|
||||
*
|
||||
@ -92,7 +115,11 @@ public class RedissonLockClient {
|
||||
* @param lockName 锁名称
|
||||
*/
|
||||
public void unlock(String lockName) {
|
||||
redissonClient.getLock(lockName).unlock();
|
||||
try {
|
||||
redissonClient.getLock(lockName).unlock();
|
||||
} catch (Exception e) {
|
||||
log.error("解锁异常,lockName=" + lockName, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
package org.jeecg.boot.starter.lock.test;
|
||||
|
||||
import org.jeecg.boot.starter.lock.annotation.JLock;
|
||||
import org.jeecg.boot.starter.lock.annotation.JRepeat;
|
||||
import org.jeecg.boot.starter.lock.annotation.LockConstant;
|
||||
import org.jeecg.boot.starter.lock.client.RedissonLockClient;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class LockService {
|
||||
|
||||
@Resource
|
||||
private RedissonLockClient redissonLockClient;
|
||||
|
||||
int n = 10;
|
||||
|
||||
/**
|
||||
* 模拟秒杀(注解方式)
|
||||
*/
|
||||
@JLock(lockKey = "#productId", expireSeconds = 5000)
|
||||
public void seckill(String productId) {
|
||||
if (n <= 0) {
|
||||
System.out.println("活动已结束,请下次再来");
|
||||
return;
|
||||
}
|
||||
System.out.println(Thread.currentThread().getName() + ":秒杀到了商品");
|
||||
System.out.println(--n);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟秒杀(编程方式)
|
||||
*/
|
||||
public void seckill2(String productId) {
|
||||
redissonLockClient.tryLock(productId, 5000);
|
||||
if (n <= 0) {
|
||||
System.out.println("活动已结束,请下次再来");
|
||||
return;
|
||||
}
|
||||
System.out.println(Thread.currentThread().getName() + ":秒杀到了商品");
|
||||
System.out.println(--n);
|
||||
redissonLockClient.unlock(productId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 测试重复提交
|
||||
*/
|
||||
@JRepeat(lockKey = "#name", lockTime = 5)
|
||||
public void reSubmit(String name) {
|
||||
try {
|
||||
Thread.sleep(1500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("提交成功" + name);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
package org.jeecg.boot.starter.lock.test;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = LockTestApplication.class)
|
||||
public class LockTest {
|
||||
@Autowired
|
||||
LockService lockService;
|
||||
|
||||
/**
|
||||
* 测试分布式锁(模拟秒杀)
|
||||
*/
|
||||
@Test
|
||||
public void test1() throws Exception {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(6);
|
||||
IntStream.range(0, 30).forEach(i -> executorService.submit(() -> {
|
||||
try {
|
||||
lockService.seckill("20120508784");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}));
|
||||
executorService.awaitTermination(30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试分布式锁(模拟秒杀)
|
||||
*/
|
||||
@Test
|
||||
public void test2() throws Exception {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(6);
|
||||
IntStream.range(0, 30).forEach(i -> executorService.submit(() -> {
|
||||
try {
|
||||
lockService.seckill2("20120508784");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}));
|
||||
executorService.awaitTermination(30, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试分布式锁(模拟重复提交)
|
||||
*/
|
||||
@Test
|
||||
public void test3() throws Exception {
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(6);
|
||||
IntStream.range(0, 20).forEach(i -> executorService.submit(() -> {
|
||||
try {
|
||||
lockService.reSubmit("test");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}));
|
||||
executorService.awaitTermination(30, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package org.jeecg.boot.starter.lock.test;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = "org.jeecg")
|
||||
@EnableAspectJAutoProxy
|
||||
public class LockTestApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(LockTestApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package org.jeecg.boot.starter.lock.test;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TestUser {
|
||||
private String userId;
|
||||
private String userName;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
spring:
|
||||
redis:
|
||||
database: 0
|
||||
host: 127.0.0.1
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 8 #最大连接数据库连接数,设 0 为没有限制
|
||||
max-idle: 8 #最大等待连接中的数量,设 0 为没有限制
|
||||
max-wait: -1ms #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
|
||||
min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
|
||||
shutdown-timeout: 100ms
|
||||
password: jeecg
|
||||
port: 6379
|
||||
jeecg :
|
||||
redisson:
|
||||
address: 127.0.0.1:6379
|
||||
password: jeecg
|
||||
type: STANDALONE
|
||||
enabled: true
|
||||
Reference in New Issue
Block a user