commit:修改微服务工程目录名称

This commit is contained in:
Jerry
2020-09-26 20:14:58 +08:00
parent d05ad53a17
commit 322b3bc19d
463 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
<?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>common</artifactId>
<groupId>com.orange.demo</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common-redis</artifactId>
<version>1.0.0</version>
<name>common-redis</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.orange.demo</groupId>
<artifactId>common-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${redisson.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,410 @@
package com.orange.demo.common.redis.cache;
import com.alibaba.fastjson.JSON;
import com.orange.demo.common.core.cache.DictionaryCache;
import com.orange.demo.common.core.exception.RedisCacheAccessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.redisson.api.RMap;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 字典数据Redis缓存对象。
*
* @param <K> 字典表主键类型。
* @param <V> 字典表对象类型。
* @author Orange Team
* @date 2020-08-08
*/
@Slf4j
public class RedisDictionaryCache<K, V> implements DictionaryCache<K, V> {
/**
* redisson客户端。
*/
protected RedissonClient redissonClient;
/**
* 数据存储对象。
*/
protected RMap<K, String> dataMap;
/**
* 字典值对象类型。
*/
protected Class<V> valueClazz;
/**
* 由于大部分场景是读取操作,所以使用读写锁提高并发的伸缩性。
*/
protected RReadWriteLock lock;
/**
* 超时时长。单位毫秒。
*/
protected static final long TIMEOUT = 2000L;
/**
* 获取字典主键数据的函数对象。
*/
protected Function<V, K> idGetter;
/**
* 当前对象的构造器函数。
*
* @param redissonClient Redisson的客户端对象。
* @param dictionaryName 字典表的名称。等同于redis hash对象的key。
* @param valueClazz 值对象的Class对象。
* @param idGetter 获取当前类主键字段值的函数对象。
* @param <K> 字典主键类型。
* @param <V> 字典对象类型
* @return 实例化后的字典内存缓存对象。
*/
public static <K, V> RedisDictionaryCache<K, V> create(
RedissonClient redissonClient,
String dictionaryName,
Class<V> valueClazz,
Function<V, K> idGetter) {
if (idGetter == null) {
throw new IllegalArgumentException("IdGetter can't be NULL.");
}
return new RedisDictionaryCache<>(redissonClient, dictionaryName, valueClazz, idGetter);
}
/**
* 构造函数。
*
* @param redissonClient Redisson的客户端对象。
* @param dictionaryName 字典表的名称。等同于redis hash对象的key。确保全局唯一。
* @param valueClazz 值对象的Class对象。
* @param idGetter 获取当前类主键字段值的函数对象。
*/
public RedisDictionaryCache(
RedissonClient redissonClient,
String dictionaryName,
Class<V> valueClazz,
Function<V, K> idGetter) {
this.redissonClient = redissonClient;
this.dataMap = redissonClient.getMap(dictionaryName + "-DICT");
this.lock = redissonClient.getReadWriteLock(dictionaryName + "-DICT-LOCK");
this.valueClazz = valueClazz;
this.idGetter = idGetter;
}
/**
* 按照数据插入的顺序返回全部字典对象的列表。
*
* @return 全部字段数据列表。
*/
@Override
public List<V> getAll() {
Collection<String> dataList;
String exceptionMessage;
try {
if (lock.readLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
dataList = dataMap.readAllValues();
} finally {
// 如果上面的操作时间超过redisson.lockWatchdogTimeout的时长
// redis会将与该锁关联的键删除此后调用unlock的时候就会抛出运行时异常。
lock.readLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::getAll] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
if (CollectionUtils.isEmpty(dataList)) {
return new LinkedList<>();
}
return dataList.stream()
.map(data -> JSON.parseObject(data, valueClazz))
.collect(Collectors.toCollection(LinkedList::new));
}
/**
* 获取缓存中与键列表对应的对象列表。
*
* @param keys 主键集合。
* @return 对象列表。
*/
@Override
public List<V> getInList(Set<K> keys) {
if (CollectionUtils.isEmpty(keys)) {
return new LinkedList<>();
}
Collection<String> dataList;
String exceptionMessage;
try {
if (lock.readLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
dataList = dataMap.getAll(keys).values();
} finally {
lock.readLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::getInList] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
if (dataList == null) {
return new LinkedList<>();
}
return dataList.stream()
.map(data -> JSON.parseObject(data, valueClazz))
.collect(Collectors.toCollection(LinkedList::new));
}
/**
* 从缓存中获取指定的数据。
*
* @param id 数据的key。
* @return 获取到的数据如果没有返回null。
*/
@Override
public V get(K id) {
if (id == null) {
return null;
}
String data;
String exceptionMessage;
try {
if (lock.readLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
data = dataMap.get(id);
} finally {
lock.readLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::get] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
if (data == null) {
return null;
}
return JSON.parseObject(data, valueClazz);
}
/**
* 获取缓存中数据条目的数量。
*
* @return 返回缓存的数据数量。
*/
@Override
public int getCount() {
return dataMap.size();
}
/**
* 将参数List中的数据保存到缓存中同时保证getAll返回的数据列表与参数列表中数据项的顺序保持一致。
*
* @param dataList 待缓存的数据列表。
*/
@Override
public void putAll(List<V> dataList) {
if (CollectionUtils.isEmpty(dataList)) {
return;
}
Map<K, String> map = dataList.stream()
.collect(Collectors.toMap(idGetter, JSON::toJSONString));
String exceptionMessage;
try {
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
dataMap.putAll(map, 1000);
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::putAll] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
/**
* 将数据存入缓存。
*
* @param id 通常为字典数据的主键。
* @param data 字典数据对象。
*/
@Override
public void put(K id, V data) {
if (id == null || data == null) {
return;
}
String exceptionMessage;
try {
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
dataMap.fastPut(id, JSON.toJSONString(data));
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::put] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
/**
* 重新加载先清空原有数据在执行putAll的操作。
*
* @param dataList 待缓存的数据列表。
* @param force true则强制刷新如果false当缓存中存在数据时不刷新。
*/
@Override
public void reload(List<V> dataList, boolean force) {
Map<K, String> map = null;
if (CollectionUtils.isNotEmpty(dataList)) {
map = dataList.stream().collect(Collectors.toMap(idGetter, JSON::toJSONString));
}
String exceptionMessage;
try {
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
// 如果不强制刷新,需要先判断缓存中是否存在数据。
if (!force && this.getCount() > 0) {
return;
}
dataMap.clear();
if (map != null) {
dataMap.putAll(map, 1000);
}
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::reload] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
/**
* 删除缓存中指定的键。
*
* @param id 待删除数据的主键。
* @return 返回被删除的对象如果主键不存在返回null。
*/
@Override
public V invalidate(K id) {
if (id == null) {
return null;
}
String data;
String exceptionMessage;
try {
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
data = dataMap.remove(id);
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::invalidate] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
if (data == null) {
return null;
}
return JSON.parseObject(data, valueClazz);
}
/**
* 删除缓存中,参数列表中包含的键。
*
* @param keys 待删除数据的主键集合。
*/
@SuppressWarnings("unchecked")
@Override
public void invalidateSet(Set<K> keys) {
if (CollectionUtils.isEmpty(keys)) {
return;
}
Object[] keyArray = keys.toArray(new Object[]{});
String exceptionMessage;
try {
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
dataMap.fastRemove((K[]) keyArray);
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::invalidateSet] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
/**
* 清空缓存。
*/
@Override
public void invalidateAll() {
String exceptionMessage;
try {
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
dataMap.clear();
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::invalidateAll] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
}

View File

@@ -0,0 +1,352 @@
package com.orange.demo.common.redis.cache;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import com.orange.demo.common.core.exception.RedisCacheAccessException;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.collections4.CollectionUtils;
import org.redisson.api.RListMultimap;
import org.redisson.api.RedissonClient;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 树形字典数据Redis缓存对象。
*
* @param <K> 字典表主键类型。
* @param <V> 字典表对象类型。
* @author Orange Team
* @date 2020-08-08
*/
@Slf4j
public class RedisTreeDictionaryCache<K, V> extends RedisDictionaryCache<K, V> {
/**
* 树形数据存储对象。
*/
private RListMultimap<K, String> allTreeMap;
/**
* 获取字典父主键数据的函数对象。
*/
protected Function<V, K> parentIdGetter;
/**
* 当前对象的构造器函数。
*
* @param redissonClient Redisson的客户端对象。
* @param dictionaryName 字典表的名称。等同于redis hash对象的key。
* @param valueClazz 值对象的Class对象。
* @param idGetter 获取当前类主键字段值的函数对象。
* @param parentIdGetter 获取当前类父主键字段值的函数对象。
* @param <K> 字典主键类型。
* @param <V> 字典对象类型
* @return 实例化后的树形字典内存缓存对象。
*/
public static <K, V> RedisTreeDictionaryCache<K, V> create(
RedissonClient redissonClient,
String dictionaryName,
Class<V> valueClazz,
Function<V, K> idGetter,
Function<V, K> parentIdGetter) {
if (idGetter == null) {
throw new IllegalArgumentException("IdGetter can't be NULL.");
}
if (parentIdGetter == null) {
throw new IllegalArgumentException("ParentIdGetter can't be NULL.");
}
return new RedisTreeDictionaryCache<>(
redissonClient, dictionaryName, valueClazz, idGetter, parentIdGetter);
}
/**
* 构造函数。
*
* @param redissonClient Redisson的客户端对象。
* @param dictionaryName 字典表的名称。等同于redis hash对象的key。
* @param valueClazz 值对象的Class对象。
* @param idGetter 获取当前类主键字段值的函数对象。
* @param parentIdGetter 获取当前类父主键字段值的函数对象。
*/
public RedisTreeDictionaryCache(
RedissonClient redissonClient,
String dictionaryName,
Class<V> valueClazz,
Function<V, K> idGetter,
Function<V, K> parentIdGetter) {
super(redissonClient, dictionaryName, valueClazz, idGetter);
this.allTreeMap = redissonClient.getListMultimap(dictionaryName + "-TREE-DICT");
this.parentIdGetter = parentIdGetter;
}
/**
* 获取该父主键的子数据列表。
*
* @param parentId 父主键Id。如果parentId为null则返回所有一级节点数据。
* @return 子数据列表。
*/
public List<V> getListByParentId(K parentId) {
List<String> dataList;
String exceptionMessage;
try {
if (lock.readLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
dataList = allTreeMap.get(parentId);
} finally {
lock.readLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisTreeDictionaryCache::getListByParentId] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
if (CollectionUtils.isEmpty(dataList)) {
return new LinkedList<>();
}
List<V> resultList = new LinkedList<>();
dataList.forEach(data -> resultList.add(JSON.parseObject(data, valueClazz)));
return resultList;
}
/**
* 将参数List中的数据保存到缓存中同时保证getAll返回的数据列表与参数列表中数据项的顺序保持一致。
*
* @param dataList 待缓存的数据列表。
*/
@Override
public void putAll(List<V> dataList) {
if (CollectionUtils.isEmpty(dataList)) {
return;
}
// 锁外执行数据结构组装,降低锁的粒度,提高并发性。
Map<K, String> map = dataList.stream()
.collect(Collectors.toMap(idGetter, JSON::toJSONString));
Multimap<K, String> treeMap = LinkedListMultimap.create();
for (V data : dataList) {
treeMap.put(parentIdGetter.apply(data), JSON.toJSONString(data));
}
Set<Map.Entry<K, Collection<String>>> entries = treeMap.asMap().entrySet();
String exceptionMessage;
try {
if (this.lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
dataMap.putAll(map, 1000);
for (Map.Entry<K, Collection<String>> entry : entries) {
allTreeMap.removeAll(entry.getKey());
allTreeMap.putAll(entry.getKey(), entry.getValue());
}
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisTreeDictionaryCache::putAll] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
/**
* 将数据存入缓存。
*
* @param id 通常为字典数据的主键。
* @param data 字典数据对象。
*/
@Override
public void put(K id, V data) {
if (id == null || data == null) {
return;
}
String stringData = JSON.toJSONString(data);
K parentId = parentIdGetter.apply(data);
String exceptionMessage;
try {
if (this.lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
String oldData = dataMap.put(id, stringData);
if (oldData != null) {
allTreeMap.remove(parentId, oldData);
}
allTreeMap.put(parentId, stringData);
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisTreeDictionaryCache::put] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
/**
* 行为等同于接口中的描述。这里之所以重写是因为不确定redisson的读写锁
* 是否为可重入锁。
*
* @param dataList 待缓存的数据列表。
* @param force true则强制刷新如果false当缓存中存在数据时不刷新。
*/
@Override
public void reload(List<V> dataList, boolean force) {
// 锁外执行数据结构组装,降低锁的粒度,提高并发性。
Map<K, String> map = null;
Set<Map.Entry<K, Collection<String>>> entries = null;
if (CollectionUtils.isNotEmpty(dataList)) {
map = dataList.stream().collect(Collectors.toMap(idGetter, JSON::toJSONString));
Multimap<K, String> treeMap = LinkedListMultimap.create();
for (V data : dataList) {
treeMap.put(parentIdGetter.apply(data), JSON.toJSONString(data));
}
entries = treeMap.asMap().entrySet();
}
String exceptionMessage;
try {
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
// 如果不强制刷新,需要先判断缓存中是否存在数据。
if (!force && this.getCount() > 0) {
return;
}
dataMap.clear();
allTreeMap.clear();
if (map != null) {
dataMap.putAll(map, 1000);
for (Map.Entry<K, Collection<String>> entry : entries) {
allTreeMap.removeAll(entry.getKey());
allTreeMap.putAll(entry.getKey(), entry.getValue());
}
}
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisDictionaryCache::reload] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
/**
* 删除缓存中指定的键。
*
* @param id 待删除数据的主键。
* @return 返回被删除的对象如果主键不存在返回null。
*/
@Override
public V invalidate(K id) {
if (id == null) {
return null;
}
V data = null;
String exceptionMessage;
try {
if (this.lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
String stringData = dataMap.remove(id);
if (stringData != null) {
data = JSON.parseObject(stringData, valueClazz);
K parentId = parentIdGetter.apply(data);
allTreeMap.remove(parentId, stringData);
}
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisTreeDictionaryCache::invalidate] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
return data;
}
/**
* 删除缓存中,参数列表中包含的键。
*
* @param keys 待删除数据的主键集合。
*/
@Override
public void invalidateSet(Set<K> keys) {
if (CollectionUtils.isEmpty(keys)) {
return;
}
String exceptionMessage;
try {
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
keys.forEach(id -> {
if (id != null) {
String stringData = dataMap.remove(id);
if (stringData != null) {
K parentId = parentIdGetter.apply(JSON.parseObject(stringData, valueClazz));
allTreeMap.remove(parentId, stringData);
}
}
});
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisTreeDictionaryCache::invalidateSet] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
/**
* 清空缓存。
*/
@Override
public void invalidateAll() {
String exceptionMessage;
try {
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
try {
dataMap.clear();
allTreeMap.clear();
} finally {
lock.writeLock().unlock();
}
} else {
throw new TimeoutException();
}
} catch (Exception e) {
exceptionMessage = String.format(
"LOCK Operation of [RedisTreeDictionaryCache::invalidateAll] encountered EXCEPTION [%s] for DICT [%s].",
e.getClass().getSimpleName(), valueClazz.getSimpleName());
log.warn(exceptionMessage);
throw new RedisCacheAccessException(exceptionMessage, e);
}
}
}

View File

@@ -0,0 +1,52 @@
package com.orange.demo.common.redis.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Redis配置类。
*
* @author Orange Team
* @date 2020-08-08
*/
@Configuration
@ConditionalOnProperty(name = "redis.jedis.enabled", havingValue = "true")
public class JedisConfig {
@Value("${redis.jedis.port}")
private Integer port;
@Value("${redis.jedis.host}")
private String redisHost;
@Value("${redis.jedis.timeout}")
private int timeout;
@Value("${redis.jedis.pool.maxTotal}")
private Integer maxTotal;
@Value("${redis.jedis.pool.maxIdle}")
private Integer maxIdle;
@Value("${redis.jedis.pool.minIdle}")
private Integer minIdle;
@Value("${redis.jedis.pool.maxWait}")
private Integer maxWait;
@Bean
public JedisPool getJedisPool() {
//Jedis配置信息
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxTotal);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMinIdle(minIdle);
jedisPoolConfig.setMaxWaitMillis(maxWait);
jedisPoolConfig.setEvictorShutdownTimeoutMillis(2000);
return new JedisPool(jedisPoolConfig, redisHost, port);
}
}

View File

@@ -0,0 +1,50 @@
package com.orange.demo.common.redis.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Redisson配置类。和Jedis一样都是Redis客户端但是Redisson提供了更多的数据结构抽象。
* 这里我们只是使用了Redisson的分布式锁以及map等数据结构作为字典缓存使用。更多用法请参考其文档。
*
* @author Orange Team
* @date 2020-08-08
*/
@Configuration
@ConditionalOnProperty(name = "redis.redisson.enabled", havingValue = "true")
public class RedissonConfig {
@Value("${redis.redisson.lockWatchdogTimeout}")
private Integer lockWatchdogTimeout;
@Value("${redis.redisson.address}")
private String address;
@Value("${redis.redisson.timeout}")
private Integer timeout;
@Value("${redis.redisson.pool.poolSize}")
private Integer poolSize;
@Value("${redis.redisson.pool.minIdle}")
private Integer minIdle;
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
// 这里config还支持其他redis集群模式可根据实际需求更换。
// 比如useClusterServers()/useMasterSlaveServers()等。
config.setLockWatchdogTimeout(lockWatchdogTimeout)
.useSingleServer()
.setAddress("redis://" + address)
.setConnectionPoolSize(poolSize)
.setConnectionMinimumIdleSize(minIdle)
.setConnectTimeout(timeout);
return Redisson.create(config);
}
}

View File

@@ -0,0 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.orange.demo.common.redis.config.JedisConfig,\
com.orange.demo.common.redis.config.RedissonConfig