新加入 redisson 分布式锁

v1.4.1
Parker 4 years ago
parent 8261636f91
commit d3259db75a

@ -25,12 +25,12 @@ package org.opsli.common.constants;
public interface DictConstants {
/** 缓存前缀 NAME */
String CACHE_PREFIX_NAME = "dict:name:";
String CACHE_PREFIX_NAME = "dict::name::";
/** 缓存前缀 VALUE*/
String CACHE_PREFIX_VALUE = "dict:value:";
String CACHE_PREFIX_VALUE = "dict::value::";
/** 缓存前缀 LIST*/
String CACHE_PREFIX_LIST = "dict:list:";
String CACHE_PREFIX_LIST = "dict::list::";
}

@ -40,6 +40,13 @@
<version>${plugins.version}</version>
</dependency>
<!-- 引入Redisson插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>
<artifactId>opsli-plugins-redisson</artifactId>
<version>${plugins.version}</version>
</dependency>
<!-- 引入EhCache插件 -->
<dependency>
<groupId>org.opsliframework.boot</groupId>

@ -0,0 +1,61 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.core.autoconfigure.conf;
import lombok.extern.slf4j.Slf4j;
import org.opsli.plugins.redisson.RedissonLock;
import org.opsli.plugins.redisson.RedissonManager;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
/**
* Redisson
*
* @author Parker
* @date 2019/6/19 11:55
*/
@Slf4j
@Configuration
@ConditionalOnProperty(name = "redisson.lock.server.enable", havingValue = "true")
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonConfig {
@Bean
@ConditionalOnMissingBean
@Order(value = 2)
public RedissonLock redissonLock(RedissonManager redissonManager) {
RedissonLock redissonLock = new RedissonLock(redissonManager);
log.info("[RedissonLock]组装完毕");
return redissonLock;
}
@Bean
@ConditionalOnMissingBean
@Order(value = 1)
public RedissonManager redissonManager(RedissonProperties redissonProperties) {
RedissonManager redissonManager =
new RedissonManager(redissonProperties);
log.info("[RedissonManager]组装完毕,当前连接方式:" + redissonProperties.getType().getDesc() +
",连接地址:" + redissonProperties.getAddress());
return redissonManager;
}
}

@ -649,7 +649,7 @@ public class CacheUtil {
public void init(CacheProperties cacheProperties){
if(cacheProperties != null){
// 获得 超级管理员
CacheUtil.PREFIX_NAME = Convert.toStr(cacheProperties.getPrefix(), "opsli") + ":";
CacheUtil.PREFIX_NAME = Convert.toStr(cacheProperties.getPrefix(), "opsli") + "::";
}
}

@ -38,6 +38,7 @@ public enum CoreMsg implements BaseMsg {
* Redis
*/
REDIS_EXCEPTION_PUSH_SUB(10200,"Redis 订阅通道失败!"),
REDIS_EXCEPTION_LOCK(10201,"无法申领分布式锁"),
/**
* Excel

@ -32,7 +32,7 @@ public class RedisCacheManager implements CacheManager {
/**
* The Redis key prefix for caches
*/
public static final String DEFAULT_CACHE_KEY_PREFIX = "shiro:cache:";
public static final String DEFAULT_CACHE_KEY_PREFIX = "shiro::cache::";
private String keyPrefix = DEFAULT_CACHE_KEY_PREFIX;
public static final String DEFAULT_PRINCIPAL_ID_FIELD_NAME = "authCacheKey or id";

@ -58,7 +58,7 @@ public class CaptchaUtil {
private static final List<CaptchaStrategy> CAPTCHA_STRATEGY_LIST;
/** 缓存前缀 */
private static final String PREFIX = "temp:captcha:";
private static final String PREFIX = "temp::captcha::";
/** 默认验证码保存 5 分钟 */
private static final int TIME_OUT = 300;
/** Redis插件 */

@ -46,7 +46,7 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
public class MenuUtil {
/** 前缀 */
public static final String PREFIX_CODE = "menu:code:";
public static final String PREFIX_CODE = "menu::code::";
/** Redis插件 */

@ -46,7 +46,7 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
public class OrgUtil {
/** 前缀 */
public static final String PREFIX_CODE = "org:userId:";
public static final String PREFIX_CODE = "org::userId::";
/** Redis插件 */

@ -48,7 +48,7 @@ public class SearchHisUtil {
/** 搜索历史缓存数据KEY */
private static final int DEFAULT_COUNT = 10;
private static final String CACHE_PREFIX = "his:username:";
private static final String CACHE_PREFIX = "his::username::";
/** Redis插件 */
private static RedisPlugin redisPlugin;

@ -46,7 +46,7 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
public class TenantUtil {
/** 前缀 */
public static final String PREFIX_CODE = "tenant:id:";
public static final String PREFIX_CODE = "tenant::id::";
/** Redis插件 */

@ -61,11 +61,11 @@ public class UserTokenUtil {
/** token 缓存名 */
public static final String TOKEN_NAME = TokenConstants.ACCESS_TOKEN;
/** 缓存前缀 */
private static final String TICKET_PREFIX = "ticket:";
private static final String TICKET_PREFIX = "ticket::";
/** 账号失败次数 */
public static final String ACCOUNT_SLIP_COUNT_PREFIX = "account:slip:count:";
public static final String ACCOUNT_SLIP_COUNT_PREFIX = "account::slip::count::";
/** 账号失败锁定KEY */
public static final String ACCOUNT_SLIP_LOCK_PREFIX = "account:slip:lock:";
public static final String ACCOUNT_SLIP_LOCK_PREFIX = "account::slip::lock::";
/** 限制登录数量 -1 为无限大 */
public static final int ACCOUNT_LIMIT_INFINITE = -1;
/** 登录配置信息 */

@ -15,7 +15,9 @@
*/
package org.opsli.core.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
@ -31,16 +33,19 @@ import org.opsli.common.exception.TokenException;
import org.opsli.core.autoconfigure.properties.GlobalProperties;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.cache.pushsub.msgs.UserMsgFactory;
import org.opsli.core.msg.CoreMsg;
import org.opsli.core.msg.TokenMsg;
import org.opsli.plugins.redis.RedisLockPlugins;
import org.opsli.plugins.redis.RedisPlugin;
import org.opsli.plugins.redis.lock.RedisLock;
import org.opsli.plugins.redisson.RedissonLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
@ -58,18 +63,18 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
public class UserUtil {
/** 前缀 */
public static final String PREFIX_ID = "userId:";
public static final String PREFIX_ID_ROLES = "userId:roles:";
public static final String PREFIX_ID_PERMISSIONS = "userId:permissions:";
public static final String PREFIX_ID_MENUS = "userId:menus:";
public static final String PREFIX_USERNAME = "username:";
public static final String PREFIX_ID = "userId::";
public static final String PREFIX_ID_ROLES = "userId::roles::";
public static final String PREFIX_ID_PERMISSIONS = "userId::permissions::";
public static final String PREFIX_ID_MENUS = "userId::menus::";
public static final String PREFIX_USERNAME = "username::";
/** Redis插件 */
private static RedisPlugin redisPlugin;
/** Redis分布式锁 */
private static RedisLockPlugins redisLockPlugins;
/** Redisson 分布式锁 */
private static RedissonLock REDISSON_LOCK;
/** 用户Service */
private static UserApi userApi;
@ -104,36 +109,35 @@ public class UserUtil {
* @return UserModel
*/
public static UserModel getUser(String userId){
// 缓存Key
String cacheKey = PREFIX_ID + userId;
// 先从缓存里拿
UserModel userModel = CacheUtil.getTimed(UserModel.class, PREFIX_ID + userId);
UserModel userModel = CacheUtil.getTimed(UserModel.class, cacheKey);
if (userModel != null){
return userModel;
}
// 拿不到 --------
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID + userId);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey);
if(hasNilFlag){
return null;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(PREFIX_ID + userId)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
userModel = CacheUtil.getTimed(UserModel.class, PREFIX_ID + userId);
userModel = CacheUtil.getTimed(UserModel.class, cacheKey);
if (userModel != null){
return userModel;
}
@ -147,18 +151,22 @@ public class UserUtil {
if(resultVo.isSuccess()){
userModel = resultVo.getData();
// 存入缓存
CacheUtil.put(PREFIX_ID + userId, userModel);
CacheUtil.put(cacheKey, userModel);
}
}catch (Exception e){
log.error(e.getMessage(),e);
log.error(e.getMessage(), e);
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
}
if(userModel == null){
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_ID + userId);
CacheUtil.putNilFlag(cacheKey);
return null;
}
@ -172,56 +180,58 @@ public class UserUtil {
* @return UserModel
*/
public static UserModel getUserByUserName(String userName){
// 缓存Key
String cacheKey = PREFIX_USERNAME + userName;
// 先从缓存里拿
UserModel userModel = CacheUtil.getTimed(UserModel.class, PREFIX_USERNAME + userName);
UserModel userModel = CacheUtil.getTimed(UserModel.class, cacheKey);
if (userModel != null){
return userModel;
}
// 拿不到 --------
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_USERNAME + userName);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey);
if(hasNilFlag){
return null;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(PREFIX_USERNAME + userName)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
userModel = CacheUtil.getTimed(UserModel.class, PREFIX_USERNAME + userName);
if (userModel != null){
userModel = CacheUtil.getTimed(UserModel.class, cacheKey);
if (userModel != null) {
return userModel;
}
// 查询数据库
ResultVo<UserModel> resultVo = userApi.getUserByUsername(userName);
if(resultVo.isSuccess()){
if (resultVo.isSuccess()) {
userModel = resultVo.getData();
// 存入缓存
CacheUtil.put(PREFIX_USERNAME + userName, userModel);
CacheUtil.put(cacheKey, userModel);
}
}catch (Exception e){
log.error(e.getMessage(),e);
log.error(e.getMessage(), e);
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
}
if(userModel == null){
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_USERNAME + userName);
CacheUtil.putNilFlag(cacheKey);
return null;
}
@ -234,80 +244,62 @@ public class UserUtil {
* @return List
*/
public static List<String> getUserRolesByUserId(String userId){
List<String> roles = null;
// 缓存Key
String cacheKey = PREFIX_ID_ROLES + userId;
List<String> roles;
// 先从缓存里拿
try {
Object obj = CacheUtil.getTimed(PREFIX_ID_ROLES + userId);
if(obj instanceof List){
List<String> list = Convert.toList(String.class, obj);
if (!list.isEmpty()) {
return list;
}
}else {
JSONArray jsonArray = Convert.convert(JSONArray.class, obj);
if (jsonArray != null && !jsonArray.isEmpty()) {
return jsonArray.toJavaList(String.class);
}
}
}catch (Exception e){
log.error(e.getMessage(), e);
Object obj = CacheUtil.getTimed(cacheKey);
roles = Convert.toList(String.class, obj);
if(CollUtil.isNotEmpty(roles)){
return roles;
}
// 拿不到 --------
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_ROLES + userId);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey);
if(hasNilFlag){
return null;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(PREFIX_ID_ROLES + userId)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
try {
Object obj = CacheUtil.getTimed(PREFIX_ID_ROLES + userId);
if(obj instanceof List){
List<String> list = Convert.toList(String.class, obj);
if (!list.isEmpty()) {
return list;
}
}else {
JSONArray jsonArray = Convert.convert(JSONArray.class, obj);
if (jsonArray != null && !jsonArray.isEmpty()) {
return jsonArray.toJavaList(String.class);
}
}
}catch (Exception ignored){}
obj = CacheUtil.getTimed(cacheKey);
roles = Convert.toList(String.class, obj);
if(CollUtil.isNotEmpty(roles)){
return roles;
}
// 查询数据库
ResultVo<List<String>> resultVo = userApi.getRolesByUserId(userId);
if(resultVo.isSuccess()){
roles = resultVo.getData();
// 存入缓存
CacheUtil.put(PREFIX_ID_ROLES + userId, roles);
CacheUtil.put(cacheKey, roles);
}
}catch (Exception e){
log.error(e.getMessage(),e);
log.error(e.getMessage(), e);
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
}
if(roles == null || roles.size() == 0){
if(CollUtil.isEmpty(roles)){
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_ID_ROLES + userId);
CacheUtil.putNilFlag(cacheKey);
return null;
}
@ -321,81 +313,63 @@ public class UserUtil {
* @return List
*/
public static List<String> getUserAllPermsByUserId(String userId){
List<String> permissions = null;
// 缓存Key
String cacheKey = PREFIX_ID_PERMISSIONS + userId;
List<String> permissions;
// 先从缓存里拿
try {
Object obj = CacheUtil.getTimed(PREFIX_ID_PERMISSIONS + userId);
if(obj instanceof List){
List<String> list = Convert.toList(String.class, obj);
if (!list.isEmpty()) {
return list;
}
}else {
JSONArray jsonArray = Convert.convert(JSONArray.class, obj);
if (jsonArray != null && !jsonArray.isEmpty()) {
return jsonArray.toJavaList(String.class);
}
}
}catch (Exception e){
log.error(e.getMessage(), e);
Object obj = CacheUtil.getTimed(cacheKey);
permissions = Convert.toList(String.class, obj);
if(CollUtil.isNotEmpty(permissions)){
return permissions;
}
// 拿不到 --------
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_PERMISSIONS + userId);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey);
if(hasNilFlag){
return null;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(PREFIX_ID_PERMISSIONS + userId)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
try {
Object obj = CacheUtil.getTimed(PREFIX_ID_PERMISSIONS + userId);
if(obj instanceof List){
List<String> list = Convert.toList(String.class, obj);
if (!list.isEmpty()) {
return list;
}
}else {
JSONArray jsonArray = Convert.convert(JSONArray.class, obj);
if (jsonArray != null && !jsonArray.isEmpty()) {
return jsonArray.toJavaList(String.class);
}
}
}catch (Exception ignored){}
obj = CacheUtil.getTimed(cacheKey);
permissions = Convert.toList(String.class, obj);
if(CollUtil.isNotEmpty(permissions)){
return permissions;
}
// 查询数据库
ResultVo<List<String>> resultVo = userApi.getAllPerms(userId);
if(resultVo.isSuccess()){
permissions = resultVo.getData();
// 存入缓存
CacheUtil.put(PREFIX_ID_PERMISSIONS + userId, permissions);
CacheUtil.put(cacheKey, permissions);
}
}catch (Exception e){
log.error(e.getMessage(),e);
log.error(e.getMessage(), e);
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
}
if(permissions == null || permissions.size() == 0){
if(CollUtil.isEmpty(permissions)){
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_ID_PERMISSIONS + userId);
CacheUtil.putNilFlag(cacheKey);
return null;
}
@ -408,101 +382,64 @@ public class UserUtil {
* @return List
*/
public static List<MenuModel> getMenuListByUserId(String userId){
List<MenuModel> menus = null;
// 缓存Key
String cacheKey = PREFIX_ID_MENUS + userId;
List<MenuModel> menus;
// 先从缓存里拿
try {
Object obj = CacheUtil.getTimed(PREFIX_ID_MENUS + userId);
if(obj instanceof List){
List<?> list = Convert.toList(obj);
if (!list.isEmpty()) {
List<MenuModel> menuModels = Lists.newArrayListWithCapacity(list.size());
for (Object menuObj : list) {
if(menuObj instanceof MenuModel){
menuModels.add((MenuModel) menuObj);
}else if(menuObj instanceof JSONObject){
JSONObject jsonObject = (JSONObject) menuObj;
MenuModel t = JSONObject.toJavaObject(jsonObject, MenuModel.class);
menuModels.add(t);
}
}
return menuModels;
}
}else {
JSONArray jsonArray = Convert.convert(JSONArray.class, obj);
if (jsonArray != null && !jsonArray.isEmpty()) {
return jsonArray.toJavaList(MenuModel.class);
}
}
}catch (Exception e){
log.error(e.getMessage(), e);
Object obj = CacheUtil.getTimed(cacheKey);
menus = Convert.toList(MenuModel.class, obj);
if(CollUtil.isNotEmpty(menus)){
return menus;
}
// 拿不到 --------
// 防止缓存穿透判断
boolean hasNilFlag = CacheUtil.hasNilFlag(PREFIX_ID_MENUS + userId);
boolean hasNilFlag = CacheUtil.hasNilFlag(cacheKey);
if(hasNilFlag){
return null;
}
// 锁凭证 redisLock 贯穿全程
RedisLock redisLock = new RedisLock();
redisLock.setLockName(PREFIX_ID_MENUS + userId)
.setAcquireTimeOut(3000L)
.setLockTimeOut(5000L);
try {
// 这里增加分布式锁 防止缓存击穿
// ============ 尝试加锁
redisLock = redisLockPlugins.tryLock(redisLock);
if(redisLock == null){
// 分布式上锁
boolean isLock = REDISSON_LOCK.tryLock(
cacheKey, 5);
if(!isLock){
// 无法申领分布式锁
log.error(CoreMsg.REDIS_EXCEPTION_LOCK.getMessage());
return null;
}
// 如果获得锁 则 再次检查缓存里有没有, 如果有则直接退出, 没有的话才发起数据库请求
try {
Object obj = CacheUtil.getTimed(PREFIX_ID_MENUS + userId);
if(obj instanceof List){
List<?> list = Convert.toList(obj);
if (!list.isEmpty()) {
List<MenuModel> menuModels = Lists.newArrayListWithCapacity(list.size());
for (Object menuObj : list) {
if(menuObj instanceof MenuModel){
menuModels.add((MenuModel) menuObj);
}else if(menuObj instanceof JSONObject){
JSONObject jsonObject = (JSONObject) menuObj;
MenuModel t = JSONObject.toJavaObject(jsonObject, MenuModel.class);
menuModels.add(t);
}
}
return menuModels;
}
}else {
JSONArray jsonArray = Convert.convert(JSONArray.class, obj);
if (jsonArray != null && !jsonArray.isEmpty()) {
return jsonArray.toJavaList(MenuModel.class);
}
}
}catch (Exception ignored){}
obj = CacheUtil.getTimed(cacheKey);
menus = Convert.toList(MenuModel.class, obj);
if(CollUtil.isNotEmpty(menus)){
return menus;
}
// 查询数据库
ResultVo<List<MenuModel>> resultVo = userApi.getMenuListByUserId(userId);
if(resultVo.isSuccess()){
menus = resultVo.getData();
// 存入缓存
CacheUtil.put(PREFIX_ID_MENUS + userId, menus);
CacheUtil.put(cacheKey, menus);
}
}catch (Exception e){
log.error(e.getMessage(),e);
log.error(e.getMessage(), e);
}finally {
// ============ 释放锁
redisLockPlugins.unLock(redisLock);
// 是否是当前线程
if(REDISSON_LOCK.isHeldByCurrentThread(cacheKey)){
// 释放锁
REDISSON_LOCK.unlock(cacheKey);
}
}
if(menus == null || menus.size() == 0){
if(CollUtil.isEmpty(menus)){
// 设置空变量 用于防止穿透判断
CacheUtil.putNilFlag(PREFIX_ID_MENUS + userId);
CacheUtil.putNilFlag(cacheKey);
return null;
}
@ -727,28 +664,25 @@ public class UserUtil {
UserUtil.redisPlugin = redisPlugin;
}
@Autowired
public void setRedisLockPlugins(RedisLockPlugins redisLockPlugins) {
UserUtil.redisLockPlugins = redisLockPlugins;
}
@Autowired
public void setUserApi(UserApi userApi) {
UserUtil.userApi = userApi;
}
/**
*
* @param globalProperties
*/
@Autowired
public void init(GlobalProperties globalProperties){
public void init(GlobalProperties globalProperties, RedissonLock redissonLock){
if(globalProperties != null && globalProperties.getAuth() != null
&& globalProperties.getAuth().getToken() != null
){
// 获得 超级管理员
UserUtil.SUPER_ADMIN = globalProperties.getAuth().getSuperAdmin();
}
UserUtil.REDISSON_LOCK = redissonLock;
}
}

@ -27,7 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class RedisLock {
private static final String LOCK_PREFIX = "lock:";
private static final String LOCK_PREFIX = "lock::";
/** 锁名称 */
private String lockName;

@ -53,7 +53,7 @@ import java.util.List;
public class RedisLockImpl implements RedisLockPlugins {
/** 锁前缀 */
private static final String LOCK_NAME_PREFIX = "lock:";
private static final String LOCK_NAME_PREFIX = "lock::";
@Autowired
private RedisPlugin redisPlugin;

@ -11,7 +11,7 @@ package org.opsli.plugins.redis.pushsub.receiver;
*/
public abstract class BaseReceiver {
public static final String BASE_CHANNEL = "listener:msg:";
public static final String BASE_CHANNEL = "listener::msg::";
private final String channel;
public BaseReceiver(String channel){

@ -0,0 +1,35 @@
## application.properties配置方式(yaml同理)
### redisson分布式锁配置--单机
redisson.lock.server.address=127.0.0.1:6379
redisson.lock.server.type=standalone
redisson.lock.server.password=
redisson.lock.server.database=1
### redisson分布式锁配置--哨兵
**redisson.lock.server.address** 格式为: sentinel.conf配置里的sentinel别名,sentinel1节点的服务IP和端口sentinel2节点的服务IP和端口sentinel3节点的服务IP和端口
<br/>比如sentinel.conf里配置为sentinel monitor my-sentinel-name 127.0.0.1 6379 2,那么这里就配置my-sentinel-name
redisson.server.address=my-sentinel-name,127.0.0.1:26379,127.0.0.1:26389,127.0.0.1:26399
redisson.server.type=sentinel
redisson.lock.server.password=
redisson.lock.server.database=1
### redisson分布式锁配置--集群方式
cluster方式至少6个节点(3主3从3主做sharding3从用来保证主宕机后可以高可用)
<br/>地址格式为: 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384
redisson.server.address=127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384
redisson.server.type=cluster
redisson.lock.server.password=
redisson.lock.server.database=1
### redisson分布式锁配置--主从
地址格式为**主节点,子节点,子节点**
<br/>比如:127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381
<br/>代表主节点:127.0.0.1:6379从节点127.0.0.1:6380127.0.0.1:6381
redisson.server.address=127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381
redisson.server.type=masterslave
redisson.lock.server.password=
redisson.lock.server.database=1

@ -0,0 +1,25 @@
<?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">
<parent>
<artifactId>opsli-plugins</artifactId>
<groupId>org.opsliframework.boot</groupId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>opsli-plugins-redisson</artifactId>
<version>${project.parent.version}</version>
<dependencies>
<!-- 集成Redisson BEGIN -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
</dependency>
<!-- 集成Redisson END -->
</dependencies>
</project>

@ -0,0 +1,122 @@
package org.opsli.plugins.redisson;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import java.util.concurrent.TimeUnit;
/**
* @Description: Redisson
*
* @author xub
* @date 2019/6/19 10:26
*/
@Slf4j
public class RedissonLock {
private static final String PREFIX = "lock::";
private RedissonManager redissonManager;
private Redisson redisson;
public RedissonLock(RedissonManager redissonManager) {
this.redissonManager = redissonManager;
this.redisson = redissonManager.getRedisson();
}
public RedissonLock() {}
/**
*
* @param lockName
* @param leaseTime
*/
public void lock(String lockName, long leaseTime) {
RLock rLock = redisson.getLock(PREFIX + lockName);
rLock.lock(leaseTime,TimeUnit.SECONDS);
}
/**
* (30
* @param lockName
*/
public void lock(String lockName) {
RLock rLock = redisson.getLock(PREFIX + lockName);
rLock.lock();
}
/**
* (tryLock
* @param lockName
* @param leaseTime
*/
public boolean tryLock(String lockName, long leaseTime) {
RLock rLock = redisson.getLock(PREFIX + lockName);
boolean getLock;
try {
getLock = rLock.tryLock( leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("获取Redisson分布式锁[异常]lockName=" + lockName, e);
e.printStackTrace();
return false;
}
return getLock;
}
/**
* (tryLock
* @param lockName
* @param leaseTime
* @param waitTime
*/
public boolean tryLock(String lockName, long leaseTime, long waitTime) {
RLock rLock = redisson.getLock(PREFIX + lockName);
boolean getLock;
try {
getLock = rLock.tryLock( waitTime, leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
log.error("获取Redisson分布式锁[异常]lockName=" + lockName, e);
e.printStackTrace();
return false;
}
return getLock;
}
/**
*
* @param lockName
*/
public void unlock(String lockName) {
redisson.getLock(PREFIX + lockName).unlock();
}
/**
* 线
* @param lockName
*/
public boolean isLock(String lockName) {
RLock rLock = redisson.getLock(PREFIX + lockName);
return rLock.isLocked();
}
/**
* 线
* @param lockName
*/
public boolean isHeldByCurrentThread(String lockName) {
RLock rLock = redisson.getLock(PREFIX + lockName);
return rLock.isHeldByCurrentThread();
}
public RedissonManager getRedissonManager() {
return redissonManager;
}
public void setRedissonManager(RedissonManager redissonManager) {
this.redissonManager = redissonManager;
}
}

@ -0,0 +1,113 @@
package org.opsli.plugins.redisson;
import cn.hutool.core.util.ClassUtil;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.Redisson;
import org.redisson.config.Config;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Set;
/**
* @Description: Redissonredisson
*
* @author xub
* @date 2019/6/19 10:16
*/
@Slf4j
public class RedissonManager {
private final Redisson redisson;
public RedissonManager(RedissonProperties redissonProperties) {
try {
//通过不同部署方式获得不同config实体
Config config = RedissonConfigFactory.getInstance().createConfig(redissonProperties);
redisson = (Redisson) Redisson.create(config);
} catch (Exception e) {
log.error("Redisson 初始化异常", e);
throw new IllegalArgumentException("请输入正确的配置," +
"connectionType必须在 standalone/sentinel/cluster/masterslave");
}
}
public Redisson getRedisson() {
return redisson;
}
/**
* Redisson
*
*/
static class RedissonConfigFactory {
/** 策略集合 */
private final Map<RedissonType, RedissonConfigService> strategyMap = Maps.newHashMap();
private RedissonConfigFactory() {
Set<Class<?>> clazzSet = ClassUtil.scanPackageBySuper(
RedissonConfigService.class.getPackage().getName()+".impl",
RedissonConfigService.class
);
for (Class<?> aClass : clazzSet) {
// 位运算 去除抽象类
if((aClass.getModifiers() & Modifier.ABSTRACT) != 0){
continue;
}
try {
Object obj = aClass.newInstance();
RedissonConfigService handler = (RedissonConfigService) obj;
// 加入集合
strategyMap.put(handler.getType(),handler);
} catch (Exception e){
log.error(e.getMessage(), e);
}
}
}
private static volatile RedissonConfigFactory factory = null;
public static RedissonConfigFactory getInstance() {
if (factory == null) {
synchronized (Object.class) {
if (factory == null) {
factory = new RedissonConfigFactory();
}
}
}
return factory;
}
/**
* ,
*
* @param redissonProperties redis
* @return Config
*/
Config createConfig(RedissonProperties redissonProperties) {
Preconditions.checkNotNull(redissonProperties);
Preconditions.checkNotNull(redissonProperties.getAddress(), "redisson.lock.server.address 不能为空!");
Preconditions.checkNotNull(redissonProperties.getType().getType(), "redisson.lock.server.password 不能为空!");
Preconditions.checkNotNull(redissonProperties.getDatabase(), "redisson.lock.server.database cannot 不能为空");
String connectionType = redissonProperties.getType().getType();
//声明配置上下文
RedissonConfigService redissonConfigService = strategyMap.get(redissonProperties.getType());
if (redissonConfigService == null){
throw new IllegalArgumentException("创建Redisson连接Config失败当前连接方式:" + connectionType);
}
return redissonConfigService.createRedissonConfig(redissonProperties);
}
}
}

@ -0,0 +1,28 @@
package org.opsli.plugins.redisson.annotation;
import java.lang.annotation.*;
/**
* @Description:
*
* @author xub
* @date 2019/6/19 9:22
*/
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DistributedLock {
/**
*
*/
String value() default "redisson";
/**
*
*/
int leaseTime() default 10;
}

@ -0,0 +1,55 @@
package org.opsli.plugins.redisson.annotation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.opsli.plugins.redisson.RedissonLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @Description: Redisson
*
* @author xub
* @date 2019/6/20 9:34
*/
@Aspect
@Component
@Slf4j
public class DistributedLockHandler {
@Autowired
private RedissonLock redissonLock;
@Around("@annotation(distributedLock)")
public Object around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) {
Object returnValue = null;
log.info("[开始]执行RedisLock环绕通知,获取Redis分布式锁开始");
//获取锁名称
String lockName = distributedLock.value();
//获取超时时间默认10秒
int leaseTime = distributedLock.leaseTime();
redissonLock.lock(lockName, leaseTime);
try {
log.info("获取Redis分布式锁[成功],加锁完成,开始执行业务逻辑...");
returnValue = joinPoint.proceed();
} catch (Throwable throwable) {
log.error("获取Redis分布式锁[异常],加锁失败", throwable);
throwable.printStackTrace();
} finally {
//如果该线程还持有该锁,那么释放该锁。如果该线程不持有该锁,说明该线程的锁已到过期时间,自动释放锁
if (redissonLock.isHeldByCurrentThread(lockName)) {
redissonLock.unlock(lockName);
}
}
log.info("释放Redis分布式锁[成功],解锁完成,结束业务逻辑...");
return returnValue;
}
}

@ -0,0 +1,29 @@
package org.opsli.plugins.redisson.constant;
/**
* @author xub
* @Description: URL
* @date 2019/6/19 9:09
*/
public enum GlobalConstant {
/** 前缀 */
REDIS_CONNECTION_PREFIX("redis://", "Redis地址配置前缀");
private final String constant_value;
private final String constant_desc;
GlobalConstant(String constant_value, String constant_desc) {
this.constant_value = constant_value;
this.constant_desc = constant_desc;
}
public String getConstant_value() {
return constant_value;
}
public String getConstant_desc() {
return constant_desc;
}
}

@ -0,0 +1,56 @@
package org.opsli.plugins.redisson.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @Description: redis
*
* @author xub
* @date 2019/6/19 9:35
*/
@ConfigurationProperties(prefix = "redisson.lock.server")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RedissonProperties {
/**
*
*/
private boolean enable;
/**
* redisipport
*/
private String address;
/**
* standalone-sentinel-cluster-masterslave-
*/
private RedissonType type = RedissonType.STANDALONE;
/**
* redis
*/
private String password;
/**
*
*/
private int database;
public RedissonProperties setPassword(String password) {
this.password = password;
return this;
}
public RedissonProperties setDatabase(int database) {
this.database = database;
return this;
}
}

@ -0,0 +1,68 @@
/**
* Copyright 2020 OPSLI https://www.opsli.com
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.opsli.plugins.redisson.enums;
/**
* @BelongsProject: opsli-boot
* @BelongsPackage: org.opsli.common.enums
* @Author: Parker
* @CreateTime: 2020-09-17 23:40
* @Description: Redisson
*/
public enum RedissonType {
/** 类型 */
STANDALONE("standalone", "单节点部署方式"),
SENTINEL("sentinel", "哨兵部署方式"),
CLUSTER("cluster", "集群方式"),
MASTER_SLAVE("master_slave", "主从部署方式");
;
private final String type;
private final String desc;
public static RedissonType getType(String type) {
RedissonType[] var1 = values();
int var2 = var1.length;
for (RedissonType e : var1) {
if (e.type.equalsIgnoreCase(type)) {
return e;
}
}
return null;
}
public String getType() {
return this.type;
}
public String getDesc() {
return this.desc;
}
// ================
RedissonType(final String type, final String desc) {
this.type = type;
this.desc = desc;
}
}

@ -0,0 +1,28 @@
package org.opsli.plugins.redisson.strategy;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.redisson.config.Config;
/**
* @Description: Redisson
*
* @author xub
* @date 2019/6/20 3:35
*/
public interface RedissonConfigService {
/**
*
* @return type
*/
RedissonType getType();
/**
* RedisConfig
* @param redissonProperties
* @return Config
*/
Config createRedissonConfig(RedissonProperties redissonProperties);
}

@ -0,0 +1,51 @@
package org.opsli.plugins.redisson.strategy.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.plugins.redisson.constant.GlobalConstant;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.config.Config;
/**
* @Description: Redisson
*
* cluster6(333sharding3)
* : 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384
*
* @author xub
* @date 2019/6/19 4:24
*/
@Slf4j
public class ClusterConfigImpl implements RedissonConfigService {
@Override
public RedissonType getType() {
return RedissonType.CLUSTER;
}
@Override
public Config createRedissonConfig(RedissonProperties redissonProperties) {
Config config = new Config();
try {
String address = redissonProperties.getAddress();
String password = redissonProperties.getPassword();
String[] addrTokens = address.split(",");
//设置cluster节点的服务IP和端口
for (String addrToken : addrTokens) {
config.useClusterServers()
.addNodeAddress(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + addrToken);
if (StringUtils.isNotBlank(password)) {
config.useClusterServers().setPassword(password);
}
}
log.info("初始化[集群部署]方式Config,redisAddress:" + address);
} catch (Exception e) {
log.error("集群部署 Redisson init error", e);
e.printStackTrace();
}
return config;
}
}

@ -0,0 +1,65 @@
package org.opsli.plugins.redisson.strategy.impl;
import cn.hutool.core.convert.Convert;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.plugins.redisson.constant.GlobalConstant;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.config.Config;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: Redisson
* : ,,
* : 127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381
* @author xub
* @date 2019/6/19 9:21
*/
@Slf4j
public class MasterslaveConfigImpl implements RedissonConfigService {
@Override
public RedissonType getType() {
return RedissonType.MASTER_SLAVE;
}
@Override
public Config createRedissonConfig(RedissonProperties redissonProperties) {
Config config = new Config();
try {
String address = redissonProperties.getAddress();
String password = redissonProperties.getPassword();
int database = redissonProperties.getDatabase();
String[] addrTokens = address.split(",");
String masterNodeAddr = addrTokens[0];
//设置主节点ip
config.useMasterSlaveServers().setMasterAddress(masterNodeAddr);
if (StringUtils.isNotBlank(password)) {
config.useMasterSlaveServers().setPassword(password);
}
config.useMasterSlaveServers().setDatabase(database);
//设置从节点,移除第一个节点,默认第一个为主节点
List<String> slaveList = Lists.newArrayList();
for (String addrToken : addrTokens) {
slaveList.add(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + addrToken);
}
slaveList.remove(0);
config.useMasterSlaveServers().addSlaveAddress(
Convert.toStrArray(slaveList));
log.info("初始化[主从部署]方式Config,redisAddress:" + address);
} catch (Exception e) {
log.error("主从部署 Redisson init error", e);
e.printStackTrace();
}
return config;
}
}

@ -0,0 +1,53 @@
package org.opsli.plugins.redisson.strategy.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.plugins.redisson.constant.GlobalConstant;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.config.Config;
/**
* @Description: Redis
*
* @author xub
* @date 2019/6/19 9:17
*/
@Slf4j
public class SentinelConfigImpl implements RedissonConfigService {
@Override
public RedissonType getType() {
return RedissonType.SENTINEL;
}
@Override
public Config createRedissonConfig(RedissonProperties redissonProperties) {
Config config = new Config();
try {
String address = redissonProperties.getAddress();
String password = redissonProperties.getPassword();
int database = redissonProperties.getDatabase();
String[] addrTokens = address.split(",");
String sentinelAliasName = addrTokens[0];
//设置redis配置文件sentinel.conf配置的sentinel别名
config.useSentinelServers().setMasterName(sentinelAliasName);
config.useSentinelServers().setDatabase(database);
if (StringUtils.isNotBlank(password)) {
config.useSentinelServers().setPassword(password);
}
//设置sentinel节点的服务IP和端口
for (int i = 1; i < addrTokens.length; i++) {
config.useSentinelServers().addSentinelAddress(GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + addrTokens[i]);
}
log.info("初始化[哨兵部署]方式Config,redisAddress:" + address);
} catch (Exception e) {
log.error("哨兵部署 Redisson init error", e);
}
return config;
}
}

@ -0,0 +1,47 @@
package org.opsli.plugins.redisson.strategy.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opsli.plugins.redisson.constant.GlobalConstant;
import org.opsli.plugins.redisson.entity.RedissonProperties;
import org.opsli.plugins.redisson.enums.RedissonType;
import org.opsli.plugins.redisson.strategy.RedissonConfigService;
import org.redisson.config.Config;
/**
* @Description: Redisson
*
* @author xub
* @date 2019/6/19 10:04
*/
@Slf4j
public class StandaloneConfigImpl implements RedissonConfigService {
@Override
public RedissonType getType() {
return RedissonType.STANDALONE;
}
@Override
public Config createRedissonConfig(RedissonProperties redissonProperties) {
Config config = new Config();
try {
String address = redissonProperties.getAddress();
String password = redissonProperties.getPassword();
int database = redissonProperties.getDatabase();
String redisAddr = GlobalConstant.REDIS_CONNECTION_PREFIX.getConstant_value() + address;
config.useSingleServer().setAddress(redisAddr);
config.useSingleServer().setDatabase(database);
//密码可以为空
if (StringUtils.isNotBlank(password)) {
config.useSingleServer().setPassword(password);
}
log.info("初始化[单机部署]方式Config,redisAddress:" + address);
} catch (Exception e) {
log.error("单机部署 Redisson init error", e);
}
return config;
}
}

@ -0,0 +1,36 @@
{
"properties": [
{
"name": "redisson.lock.server.enable",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"type": "java.lang.Boolean",
"defaultValue": false,
"description": "redissonLock 是否启用."
},
{
"name": "redisson.lock.server.address",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"type": "java.lang.String",
"defaultValue": "127.0.0.1:6379",
"description": "redis主机地址ipport有多个用半角逗号分隔."
},
{
"name": "redisson.lock.server.type",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"description": "连接类型支持standalone-单机节点sentinel-哨兵cluster-集群masterslave-主从."
},
{
"name": "redisson.lock.server.password",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"type": "java.lang.String",
"description": "redis 连接密码."
},
{
"name": "redisson.lock.server.database",
"sourceType": "org.opsli.plugins.redisson.entity.RedissonProperties",
"type": "java.lang.Integer",
"defaultValue": 0,
"description": "选取那个数据库 ."
}
]
}

@ -20,6 +20,7 @@
<module>opsli-plugins-redis</module>
<module>opsli-plugins-ehcache</module>
<module>opsli-plugins-excel</module>
<module>opsli-plugins-redisson</module>
</modules>
<dependencyManagement>

@ -44,6 +44,15 @@ spring:
#password: 12345678
#driver-class-name: com.mysql.cj.jdbc.Driver
# Redisson 分布式锁
redisson:
lock:
server:
enable: true
type: standalone
address: "127.0.0.1:6379"
password: 123456
database: 0
# knife4j 文档 配置
knife4j:
@ -59,7 +68,6 @@ knife4j:
production: false
# opsli 自定义配置
opsli:
# 演示模式
@ -71,3 +79,4 @@ opsli:
# 系统日志
log:
path: /var/log

@ -44,6 +44,15 @@ spring:
#password: 12345678
#driver-class-name: com.mysql.cj.jdbc.Driver
# Redisson 分布式锁
redisson:
lock:
server:
enable: true
type: standalone
address: "127.0.0.1:6379"
password: 123456
database: 0
# knife4j 文档 配置
knife4j:

@ -116,6 +116,13 @@
<version>${jwt.version}</version>
</dependency>
<!-- Redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.15.0</version>
</dependency>
</dependencies>
</dependencyManagement>

Loading…
Cancel
Save