springboot 整合redis ,在项目启动时加载redis缓存

因为在项目中,会有字典表,机构表,用户表,这些一般情况下,数据发生改变的的概率比较小,而且经常涉及到查询,转码,查询数据库的频率较高,因此在项目启动时将这些数据表加载到缓存中,以便使用。

redis是一种高级的key:value存储系统,其中value支持五种数据类型:

1.字符串(strings)

2.字符串列表(lists)

3.字符串集合(sets)

4.有序字符串集合(sorted sets)

5.哈希(hashes)

 

1.配置redis  jar包

 
            org.springframework.boot
            spring-boot-starter-data-redis
 

2.配置yml文件

 redis:
    database: 2
    host: IP地址
    port: 6379
    password: 1

3.初始化缓存步骤

 如果存入redis 的数据量较大,可以采用线程池方式,如果数据量小。可不用

@Configuration
@EnableAsync
public class AsyncConfig {

	@Bean
	public TaskExecutor taskExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		// 设置核心线程数
		executor.setCorePoolSize(10);
		// 设置最大线程数
		executor.setMaxPoolSize(20);
		// 设置队列容量
		executor.setQueueCapacity(40);
		// 设置线程活跃时间(秒)
		executor.setKeepAliveSeconds(60);
		// 设置默认线程名称
		executor.setThreadNamePrefix("async-");
		// 设置拒绝策略
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		// 等待所有任务结束后再关闭线程池
		executor.setWaitForTasksToCompleteOnShutdown(true);

		return executor;
	}
}
/**
 * 启动加载缓存
 *
 * @author 
 */
@Component
public class InitCache implements ApplicationRunner {

	@Autowired
	private ICacheService cache;

	@Override
	@Async
	public void run(ApplicationArguments arg) throws Exception {
		// 加载字典表缓存
		cache.initDictCache();
		// 加载表达式缓存
		cache.initExpressionCache();
	}
}

4.加载字典表缓存

serviceImpl实现类

	@Override
	public void initDictCache() {
		List systemDictList = systemDictMapper.querySystemDictTable();
		if (CollectionUtils.isNotEmpty(systemDictList)) {
			for (SystemDictTableEntity systemDictTableEntity : systemDictList) {
				if (null != systemDictTableEntity) {
					if (StringUtils.isNotBlank(systemDictTableEntity.getDictValue())
							&& StringUtils.isNotBlank(systemDictTableEntity.getDictKey())) {
						RedisUtils.set(RedisKeyPrefix.REDIS_SYSTEM_DICT_KEY + systemDictTableEntity.getDictKey(),
								systemDictTableEntity.getDictValue());
					}
				}
			}
		}
	}

线程池方式加载缓存:

 实现类需要注入前面写的线程池的配置类

   @Autowired
    private TaskExecutor taskExecutor;
 

@Override
	public void initExpressionCache() {
		long start = System.currentTimeMillis();
		log.info("Start Loading Expression into redis cache...");

		// 查询表达式全量数据
		List expressionCacheDtoList = mapper.getExpression();

		// 校验是否有数据需要加载缓存
		if (CollectionUtils.isEmpty(expressionCacheDtoList)) {
			log.info("There Is Nothing Need To Cache!");
			return;
		}

		// 需要处理的任务总数
		int pageCount = expressionCacheDtoList.size();

		// 每条线程处理的任务数
		int pageSize = 300;

		// 计算需要开启多少条线程
		int threadCount = pageCount % pageSize == ConstantNumber.ZERO ? pageCount / pageSize
				: pageCount / pageSize + ConstantNumber.ONE;

		// 开启threadCount条线程
		for (int pageNumber = 1; pageNumber <= threadCount; pageNumber++) {
			// 计算分页参数
			final int executeNumber = pageSize * pageNumber;
			taskExecutor.execute(() -> executeCache(expressionCacheDtoList, pageCount, pageSize, executeNumber));
		}

		// 计算完成任务消耗时间
		double cost = (System.currentTimeMillis() - start) / 1000.000;
		log.info("Started Loading Expression Cache in {}", cost + " seconds");
	}
/**
	 * 将字段表达式刷入REDIS缓存
	 * 
	 * @param expressionCacheDtoList
	 * @param pageCount
	 * @param pageSize
	 * @param executeNumber
	 */
	private void executeCache(List expressionCacheDtoList, int pageCount, int pageSize,
			int executeNumber) {

		// 校验执行最大数量是否大于总计数
		executeNumber = executeNumber < pageCount ? executeNumber : pageCount;

		// 声明参数
		String expression;
		Integer columnId;
		Integer expressionTypeId;
		StringBuilder sb = new StringBuilder();

		// 多线程分页处理
		// 例如Thread-1处理0(含)~300(不含),Thread-2处理300~600(不含)
		for (int j = executeNumber - pageSize; j < executeNumber; j++) {
			ExpressionCacheDto expressionCacheDto = expressionCacheDtoList.get(j);
			if (expressionCacheDto != null) {
				// 清空StringBuilder
				sb.delete(ConstantNumber.ZERO, sb.length());

				// 获取字段Value
				expression = expressionCacheDto.getExpression();
				columnId = expressionCacheDto.getColumnId();
				expressionTypeId = expressionCacheDto.getExpressionTypeId();

				// 组织RedisKey
				sb.append(RedisKeyPrefix.REDIS_EXPRESSION_KEY).append(columnId).append(UNDERLINE)
						.append(expressionTypeId);

				// 存入缓存
				RedisUtils.set(sb.toString(), expression);
			} else {
				log.info("cache value is null...");
			}
		}
	}

 

5  .RedisUtil 类

package cn.com.citydo.web.util;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.serializer.SerializerFeature;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * Redis缓存工具类
 * 
 * @author yss
 *
 */
@Component
@Slf4j
public class RedisUtils {

	private static RedisTemplate redisTemplate;

	@Autowired
	public void setRedisTemplate(RedisTemplate redisTemplate) {
		if (null == redisTemplate) {
			log.info("Redis初始化配置失败,请检查配置项");
		} else {
			log.info("Redis初始化配置注入成功!");
		}
		RedisUtils.redisTemplate = redisTemplate;
	}

	/**
	 * 指定缓存失效时间
	 * 
	 * @param key
	 *            键
	 * @param time
	 *            时间(秒)
	 * @return
	 */
	public static boolean expire(String key, long time) {
		try {
			if (time > 0) {
				redisTemplate.expire(key, time, TimeUnit.SECONDS);
			}
			return true;
		} catch (Exception e) {
			log.error("expire() is error : {}", e);
			return false;
		}
	}

	/**
	 * 根据key 获取过期时间
	 * 
	 * @param key
	 *            键 不能为null
	 * @return 时间(秒) 返回0代表为永久有效
	 */
	public static long getExpire(String key) {
		return redisTemplate.getExpire(key, TimeUnit.SECONDS);
	}

	/**
	 * 判断key是否存在
	 * 
	 * @param key
	 *            键
	 * @return true 存在 false不存在
	 */
	public static boolean hasKey(String key) {
		try {
			return redisTemplate.hasKey(key);
		} catch (Exception e) {
			log.error("hasKey() is error : {}", e);
			return false;
		}
	}

	/**
	 * 普通缓存获取
	 * 
	 * @param key
	 *            键
	 * @return 值
	 */
	public static Object get(String key) {
		return key == null ? null : redisTemplate.opsForValue().get(key);
	}

	/**
	 * 普通缓存放入
	 * 
	 * @param key
	 *            键
	 * @param value
	 *            值
	 * @return true成功 false失败
	 */
	public static boolean set(String key, Object value) {
		try {
			redisTemplate.opsForValue().set(key, value);
			return true;
		} catch (Exception e) {
			log.error("set() is error : {}", e);
			return false;
		}

	}

	/**
	 * 普通缓存放入并设置时间
	 * 
	 * @param key
	 *            键
	 * @param value
	 *            值
	 * @param time
	 *            时间(秒) time要大于0 如果time小于等于0 将设置无限期
	 * @return true成功 false 失败
	 */
	public static boolean set(String key, Object value, long time) {
		try {
			if (time > 0) {
				redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
			} else {
				set(key, value);
			}
			return true;
		} catch (Exception e) {
			log.error("set() is error : {}", e);
			return false;
		}
	}

	/**
	 * HashGet
	 * 
	 * @param key
	 *            键 不能为null
	 * @param item
	 *            项 不能为null
	 * @return 值
	 */
	public static Object hget(String key, String item) {
		return redisTemplate.opsForHash().get(key, item);
	}

	/**
	 * 获取hashKey对应的所有键值
	 * 
	 * @param key
	 *            键
	 * @return 对应的多个键值
	 */
	public static Map hmget(String key) {
		return redisTemplate.opsForHash().entries(key);
	}

	/**
	 * HashSet
	 * 
	 * @param key
	 *            键
	 * @param map
	 *            对应多个键值
	 * @return true 成功 false 失败
	 */
	public static boolean hmset(String key, Map map) {
		try {
			redisTemplate.opsForHash().putAll(key, map);
			return true;
		} catch (Exception e) {
			log.error("hmset() is error : {}", e);
			return false;
		}
	}

	/**
	 * HashSet 并设置时间
	 * 
	 * @param key
	 *            键
	 * @param map
	 *            对应多个键值
	 * @param time
	 *            时间(秒)
	 * @return true成功 false失败
	 */
	public static boolean hmset(String key, Map map, long time) {
		try {
			redisTemplate.opsForHash().putAll(key, map);
			if (time > 0) {
				expire(key, time);
			}
			return true;
		} catch (Exception e) {
			log.error("hmset() is error : {}", e);
			return false;
		}
	}

	/**
	 * 向一张hash表中放入数据,如果不存在将创建
	 * 
	 * @param key
	 *            键
	 * @param item
	 *            项
	 * @param value
	 *            值
	 * @return true 成功 false失败
	 */
	public static boolean hset(String key, String item, Object value) {
		try {
			redisTemplate.opsForHash().put(key, item, value);
			return true;
		} catch (Exception e) {
			log.error("hset() is error : {}", e);
			return false;
		}
	}

	/**
	 * 向一张hash表中放入数据,如果不存在将创建
	 * 
	 * @param key
	 *            键
	 * @param item
	 *            项
	 * @param value
	 *            值
	 * @param time
	 *            时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
	 * @return true 成功 false失败
	 */
	public static boolean hset(String key, String item, Object value, long time) {
		try {
			redisTemplate.opsForHash().put(key, item, value);
			if (time > 0) {
				expire(key, time);
			}
			return true;
		} catch (Exception e) {
			log.error("hset() is error : {}", e);
			return false;
		}
	}

	/**
	 * 删除hash表中的值
	 * 
	 * @param key
	 *            键 不能为null
	 * @param item
	 *            项 可以使多个 不能为null
	 */
	public static void hdel(String key, Object... item) {
		redisTemplate.opsForHash().delete(key, item);
	}

	/**
	 * 判断hash表中是否有该项的值
	 * 
	 * @param key
	 *            键 不能为null
	 * @param item
	 *            项 不能为null
	 * @return true 存在 false不存在
	 */
	public static boolean hHasKey(String key, String item) {
		return redisTemplate.opsForHash().hasKey(key, item);
	}

	/**
	 * hash递增 如果不存在,就会创建一个 并把新增后的值返回
	 * 
	 * @param key
	 *            键
	 * @param item
	 *            项
	 * @param by
	 *            要增加几(大于0)
	 * @return
	 */
	public static double hincr(String key, String item, double by) {
		return redisTemplate.opsForHash().increment(key, item, by);
	}

	/**
	 * hash递减
	 * 
	 * @param key
	 *            键
	 * @param item
	 *            项
	 * @param by
	 *            要减少记(小于0)
	 * @return
	 */
	public static double hdecr(String key, String item, double by) {
		return redisTemplate.opsForHash().increment(key, item, -by);
	}

	/**
	 * 根据key获取Set中的所有值
	 * 
	 * @param key
	 *            键
	 * @return
	 */
	public static Set sGet(String key) {
		try {
			return redisTemplate.opsForSet().members(key);
		} catch (Exception e) {
			log.error("sGet() is error : {}", e);
			return null;
		}
	}

	/**
	 * 根据value从一个set中查询,是否存在
	 * 
	 * @param key
	 *            键
	 * @param value
	 *            值
	 * @return true 存在 false不存在
	 */
	public static boolean sHasKey(String key, Object value) {
		try {
			return redisTemplate.opsForSet().isMember(key, value);
		} catch (Exception e) {
			log.error("sHasKey() is error : {}", e);
			return false;
		}
	}

	/**
	 * 将数据放入set缓存
	 * 
	 * @param key
	 *            键
	 * @param values
	 *            值 可以是多个
	 * @return 成功个数
	 */
	public static long sSet(String key, Object... values) {
		try {
			return redisTemplate.opsForSet().add(key, values);
		} catch (Exception e) {
			log.error("sSet() is error : {}", e);
			return 0;
		}
	}

	/**
	 * 将set数据放入缓存
	 * 
	 * @param key
	 *            键
	 * @param time
	 *            时间(秒)
	 * @param values
	 *            值 可以是多个
	 * @return 成功个数
	 */
	public static long sSetAndTime(String key, long time, Object... values) {
		try {
			Long count = redisTemplate.opsForSet().add(key, values);
			if (time > 0) {
				expire(key, time);
			}
			return count;
		} catch (Exception e) {
			log.error("sSetAndTime() is error : {}", e);
			return 0;
		}
	}

	/**
	 * 获取set缓存的长度
	 * 
	 * @param key
	 *            键
	 * @return
	 */
	public static long sGetSetSize(String key) {
		try {
			return redisTemplate.opsForSet().size(key);
		} catch (Exception e) {
			log.error("sGetSetSize() is error : {}", e);
			return 0;
		}
	}

	/**
	 * 移除值为value的
	 * 
	 * @param key
	 *            键
	 * @param values
	 *            值 可以是多个
	 * @return 移除的个数
	 */
	public static long setRemove(String key, Object... values) {
		try {
			Long count = redisTemplate.opsForSet().remove(key, values);
			return count;
		} catch (Exception e) {
			log.error("setRemove() is error : {}", e);
			return 0;
		}
	}

	/**
	 * 获取list缓存的内容
	 * 
	 * @param key
	 *            键
	 * @param start
	 *            开始
	 * @param end
	 *            结束 0 到 -1代表所有值
	 * @return
	 */
	public static List lGet(String key, long start, long end) {
		try {
			return redisTemplate.opsForList().range(key, start, end);
		} catch (Exception e) {
			log.error("lGet() is error : {}", e);
			return null;
		}
	}

	/**
	 * 获取list缓存的内容
	 * 
	 * @param key
	 *            键
	 * @return
	 */
	public static List lGet(String key) {
		return lGet(key, 0, -1);
	}

	/**
	 * 获取list缓存的长度
	 * 
	 * @param key
	 *            键
	 * @return
	 */
	public static long lGetListSize(String key) {
		try {
			return redisTemplate.opsForList().size(key);
		} catch (Exception e) {
			log.error("lGetListSize() is error : {}", e);
			return 0;
		}
	}

	/**
	 * 通过索引 获取list中的值
	 * 
	 * @param key
	 *            键
	 * @param index
	 *            索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
	 * @return
	 */
	public static Object lGetIndex(String key, long index) {
		try {
			return redisTemplate.opsForList().index(key, index);
		} catch (Exception e) {
			log.error("lGetIndex() is error : {}", e);
			return null;
		}
	}

	/**
	 * 将list放入缓存
	 * 
	 * @param key
	 *            键
	 * @param value
	 *            值
	 * @param time
	 *            时间(秒)
	 * @return
	 */
	public static boolean lSet(String key, Object value) {
		try {
			redisTemplate.opsForList().rightPush(key, value);
			return true;
		} catch (Exception e) {
			log.error("lSet() is error : {}", e);
			return false;
		}
	}

	/**
	 * 将list放入缓存
	 * 
	 * @param key
	 *            键
	 * @param value
	 *            值
	 * @param time
	 *            时间(秒)
	 * @return
	 */
	public static boolean lSet(String key, Object value, long time) {
		try {
			redisTemplate.opsForList().rightPush(key, value);
			if (time > 0) {
				expire(key, time);
			}
			return true;
		} catch (Exception e) {
			log.error("lSet() is error : {}", e);
			return false;
		}
	}

	/**
	 * 将list放入缓存
	 * 
	 * @param key
	 *            键
	 * @param value
	 *            值
	 * @param time
	 *            时间(秒)
	 * @return
	 */
	public static boolean lSet(String key, List value) {
		try {
			redisTemplate.opsForList().rightPushAll(key, value);
			return true;
		} catch (Exception e) {
			log.error("lSet() is error : {}", e);
			return false;
		}
	}

	/**
	 * 将list放入缓存
	 * 
	 * @param key
	 *            键
	 * @param value
	 *            值
	 * @param time
	 *            时间(秒)
	 * @return
	 */
	public static boolean lSet(String key, List value, long time) {
		try {
			redisTemplate.opsForList().rightPushAll(key, value);
			if (time > 0) {
				expire(key, time);
			}
			return true;
		} catch (Exception e) {
			log.error("lSet() is error : {}", e);
			return false;
		}
	}

	/**
	 * 根据索引修改list中的某条数据
	 * 
	 * @param key
	 *            键
	 * @param index
	 *            索引
	 * @param value
	 *            值
	 * @return
	 */
	public static boolean lUpdateIndex(String key, long index, Object value) {
		try {
			redisTemplate.opsForList().set(key, index, value);
			return true;
		} catch (Exception e) {
			log.error("lUpdateIndex() is error : {}", e);
			return false;
		}
	}

	/**
	 * 移除N个值为value
	 * 
	 * @param key
	 *            键
	 * @param count
	 *            移除多少个
	 * @param value
	 *            值
	 * @return 移除的个数
	 */
	public static long lRemove(String key, long count, Object value) {
		try {
			Long remove = redisTemplate.opsForList().remove(key, count, value);
			return remove;
		} catch (Exception e) {
			log.error("lRemove() is error : {}", e);
			return 0;
		}
	}

	/**
	 * 
	 * 获取对象
	 * 
	 * @param key
	 * @param clazz
	 * @return
	 */
	public static  T getObjectBean(String key, Class clazz) {

		String value = (String) redisTemplate.opsForValue().get(key);
		return parseJson(value, clazz);
	}

	/**
	 * 存放对象
	 * 
	 * @param key
	 * @param obj
	 */
	public static  void setObjectBean(String key, T obj) {
		if (obj == null) {
			return;
		}

		String value = toJson(obj);
		redisTemplate.opsForValue().set(key, value);
	}

	/**
	 * 存放对象并返回该对象
	 * 
	 * @param key
	 * @param obj
	 */
	public static  T getAndSet(String key, T obj, Class clazz) {
		if (obj == null) {
			return getObjectBean(key, clazz);
		}
		String value = (String) redisTemplate.opsForValue().getAndSet(key, toJson(obj));
		return parseJson(value, clazz);
	}

	/**
	 * 原子自增
	 * 
	 * @param key
	 * @return
	 */
	public static long generate(String key) {
		RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
		return counter.incrementAndGet();
	}

	/**
	 * A原子自增
	 * 
	 * @param key
	 * @param expireTime
	 * @return
	 */
	public static long generate(String key, Date expireTime) {
		RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
		counter.expireAt(expireTime);
		return counter.incrementAndGet();
	}

	/**
	 * 原子自增
	 * 
	 * @param key
	 * @param increment
	 * @return
	 */
	public static long generate(String key, int increment) {
		RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
		return counter.addAndGet(increment);
	}

	/**
	 * 原子自增
	 * 
	 * @param key
	 * @param increment
	 * @param expireTime
	 * @return
	 */
	public static long generate(String key, int increment, Date expireTime) {
		RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
		counter.expireAt(expireTime);
		return counter.addAndGet(increment);
	}

	/**
	 * 序列化对象为JSONString
	 * 
	 * @param obj
	 * @return
	 */
	public static String toJson(Object obj) {
		return JSON.toJSONString(obj, SerializerFeature.SortField);
	}

	/**
	 * 序列化JSON为ObjectBean
	 * 
	 * @param obj
	 * @return
	 */
	public static  T parseJson(String json, Class clazz) {
		return JSON.parseObject(json, clazz);
	}

	/**
	 * 序列化List对象
	 * 
	 * @param key
	 * @param clazz
	 * @return
	 */
	public static  List getList(String key, Class clazz) {
		try {
			Object cache = get(key);
			if (null != cache && StringUtils.isNotBlank(cache.toString())) {
				List cacheList = JSONArray.parseArray(JSONArray.parseArray(cache.toString()).toJSONString(), clazz);
				return cacheList;
			}
		} catch (Exception e) {
			log.error("redis查询异常,e:", e);
		}
		return null;
	}

	/**
	 * 将List作为JSONString存入缓存
	 * 
	 * @param key
	 * @param list
	 */
	public static  void setList(String key, List list) {
		if (StringUtils.isBlank(key) || CollectionUtils.isEmpty(list)) {
			return;
		}
		set(key, toJson(list));
	}

}
 
  


 

你可能感兴趣的:(redis,springboot)