redis是一种nosql数据库,以
本篇基于SpringBoot + Redis实现数据缓存以及分库存储,首先我们要知道,SpringBoot整合Redis有两种方式,分别是Jedis和RedisTemplate,这两者有何区别?
Jedis是Redis官方推荐的面向Java的操作Redis的客户端,而RedisTemplate是SpringDataRedis中对JedisApi的高度封装。其实在SpringBoot的官网上我们也能看到,官方现在推荐的是SpringDataRedis形式,相对于Jedis来说可以方便地更换Redis的Java客户端,其比Jedis多了自动管理连接池的特性,方便与其他Spring框架进行搭配使用如:SpringCache。
具体分为:添加依赖+redis配置信息+JedisPool工厂+RedisService(包含序列化)
redis.clients
jedis
3.1.0
com.alibaba
fastjson
1.2.62
经常用到的参数
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=123456
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=1024
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=10000
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=200
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=10000
这个和下文对应
redis.host=localhost
redis.port=6379
#连接超时时间
redis.timeout=3
redis.password=123456
#连接池配置
#最大连接数
redis.poolMaxTotal=10
#最大空闲连接数
redis.poolMaxIdle=10
#最大等待连接数
redis.poolMaxWait=3
必须要写的是Redis服务器地址、连接端口、连接密码
@Component
@ConfigurationProperties(prefix = "redis")
public class RedisConfig {
private String host;
private int port;
private int timeout;//秒
private String password;
private int poolMaxTotal;
private int poolMaxIdle;
private int poolMaxWait;//秒
//别忘了加get/set方法
}
@Service
public class JedisPoolFactory {
@Autowired
RedisConfig redisConfig;
@Bean
public JedisPool JedisPoolFactory(){
System.out.println(redisConfig.toString());
JedisPoolConfig poolConfig=new JedisPoolConfig();
poolConfig.setMaxIdle(redisConfig.getPoolMaxIdle());
poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait()*1000);
JedisPool jp=new JedisPool(poolConfig,redisConfig.getHost(),redisConfig.getPort()
,redisConfig.getTimeout()*1000,redisConfig.getPassword(),0);
return jp;
}
}
得到一个JedisPool 的Bean
我这里KeyPrefix 是一个key的前缀,防止相同的key给予不同的含义。如果只是用来学习整合Redis的技术,在这里可以忽略KeyPrefix,看原理。
我写了常用的redis操作的get、set、exists、incr、decr方法
序列化的beanToString和stringToBean方法,用到的是import com.alibaba.fastjson.JSON;
@Service
public class RedisService {
@Autowired
JedisPool jedisPool;
/**
* 获取单个对象
* @param prefix
* @param key
* @param clazz
* @param
* @return
*/
public T get(KeyPrefix prefix,String key,Class clazz){
Jedis jedis =null;
try {
jedis = jedisPool.getResource();
//生成真正的key
String realKey =prefix.getPrefix()+key;
String str = jedis.get(realKey);
T t=stringToBean(str,clazz);
return t;
}finally {
returnToPool(jedis);
}
}
/**
* 设置对象
* @param prefix
* @param key
* @param value
* @param
* @return
*/
public boolean set(KeyPrefix prefix,String key,T value){
Jedis jedis =null;
try {
jedis = jedisPool.getResource();
String str=beanToString(value);
if (str==null||str.length()<=0)
return false;
//生成真正的key
String realKey =prefix.getPrefix()+key;
int seconds=prefix.expireSeconds();
if (seconds<=0){
jedis.set(realKey,str);
} else {
jedis.setex(realKey,seconds,str);
}
jedis.set(realKey, str);
return true;
}finally {
returnToPool(jedis);
}
}
/**
* 判断是否存在
* @param prefix
* @param key
* @param
* @return
*/
public boolean exists(KeyPrefix prefix,String key){
Jedis jedis =null;
try {
jedis = jedisPool.getResource();
//生成真正的key
String realKey =prefix.getPrefix()+key;
return jedis.exists(realKey);
}finally {
returnToPool(jedis);
}
}
/**
* 增加值
* @param prefix
* @param key
* @param
* @return
*/
public Long incr(KeyPrefix prefix,String key){
Jedis jedis =null;
try {
jedis = jedisPool.getResource();
//生成真正的key
String realKey =prefix.getPrefix()+key;
return jedis.incr(realKey);
}finally {
returnToPool(jedis);
}
}
/**
* 减少值
* @param prefix
* @param key
* @param
* @return
*/
public Long decr(KeyPrefix prefix,String key){
Jedis jedis =null;
try {
jedis = jedisPool.getResource();
//生成真正的key
String realKey =prefix.getPrefix()+key;
return jedis.decr(realKey);
}finally {
returnToPool(jedis);
}
}
private String beanToString(T value) {
if (value==null)
return null;
Class> aClass = value.getClass();
if (aClass==int.class||aClass==Integer.class){
return ""+value;
}else if (aClass==String.class){
return (String) value;
}else if (aClass==long.class||aClass==Long.class){
return ""+value;
}else {
return JSON.toJSONString(value);
}
}
private T stringToBean(String str,Class aClass) {
if (str==null||str.length()<=0||aClass==null)
return null;
if (aClass==int.class||aClass==Integer.class){
return (T)Integer.valueOf(str);
}else if (aClass==String.class){
return (T)str;
}else if (aClass==long.class||aClass==Long.class){
return (T)Long.valueOf(str);
}else {
return JSON.toJavaObject(JSON.parseObject(str),aClass);
}
}
private void returnToPool(Jedis jedis) {
if (jedis!=null){
jedis.close();
}
}
}
具体分为:添加依赖+redis配置信息+RedisTemplate+序列化+RedisService
redis.clients
jedis
${redis.version}
org.springframework.data
spring-data-redis
${spring.redis.version}
#Matser的ip地址
redis.hostName=localhost
#端口号
redis.port=6379
#如果有密码
redis.password=123456
#客户端超时时间单位是毫秒 默认是2000
redis.timeout=10000
#最大空闲数
redis.maxIdle=300
#连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal
#redis.maxActive=600
#控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性
redis.maxTotal=1000
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=1000
#连接的最小空闲时间 默认1800000毫秒(30分钟)
redis.minEvictableIdleTimeMillis=300000
#每次释放连接的最大数目,默认3
redis.numTestsPerEvictionRun=1024
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
redis.timeBetweenEvictionRunsMillis=30000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
redis.testOnBorrow=true
#在空闲时检查有效性, 默认false
redis.testWhileIdle=true
必须要写的是Redis服务器地址、连接端口、连接密码
@Configuration
@PropertySource("classpath:redis.properties")
@Slf4j
public class RedisConfig {
@Value("${redis.hostName}")
private String hostName;
@Value("${redis.password}")
private String password;
@Value("${redis.port}")
private Integer port;
@Value("${redis.maxIdle}")
private Integer maxIdle;
@Value("${redis.timeout}")
private Integer timeout;
@Value("${redis.maxTotal}")
private Integer maxTotal;
@Value("${redis.maxWaitMillis}")
private Integer maxWaitMillis;
@Value("${redis.minEvictableIdleTimeMillis}")
private Integer minEvictableIdleTimeMillis;
@Value("${redis.numTestsPerEvictionRun}")
private Integer numTestsPerEvictionRun;
@Value("${redis.timeBetweenEvictionRunsMillis}")
private long timeBetweenEvictionRunsMillis;
@Value("${redis.testOnBorrow}")
private boolean testOnBorrow;
@Value("${redis.testWhileIdle}")
private boolean testWhileIdle;
/**
* @auther: zhangyingqi
* @date: 17:52 2018/8/28
* @param: []
* @return: org.springframework.data.redis.connection.jedis.JedisConnectionFactory
* @Description: Jedis配置
*/
@Bean
public JedisConnectionFactory JedisConnectionFactory(){
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration ();
redisStandaloneConfiguration.setHostName(hostName);
redisStandaloneConfiguration.setPort(port);
//由于我们使用了动态配置库,所以此处省略
//redisStandaloneConfiguration.setDatabase(database);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
jedisClientConfiguration.connectTimeout(Duration.ofMillis(timeout));
JedisConnectionFactory factory = new JedisConnectionFactory(redisStandaloneConfiguration,
jedisClientConfiguration.build());
return factory;
}
/**
* @auther: zhangyingqi
* @date: 17:52 2018/8/28
* @param: [redisConnectionFactory]
* @return: com.springboot.demo.base.utils.RedisTemplate
* @Description: 实例化 RedisTemplate 对象
*/
@Bean
public RedisTemplate functionDomainRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
log.info("RedisTemplate实例化成功!");
RedisTemplate redisTemplate = new RedisTemplate();
initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
return redisTemplate;
}
/**
* @auther: zhangyingqi
* @date: 17:52 2018/8/28
* @param: []
* @return: org.springframework.data.redis.serializer.RedisSerializer
* @Description: 引入自定义序列化
*/
@Bean
public RedisSerializer fastJson2JsonRedisSerializer() {
return new FastJson2JsonRedisSerializer
在这里就得到了一个RedisTemplate的Bean
引入自定义序列化,防止特殊情况报错
public class FastJson2JsonRedisSerializer implements RedisSerializer {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class clazz;
public FastJson2JsonRedisSerializer(Class clazz) {
super(); this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return (T) JSON.parseObject(str, clazz);
}
}
在这里我只给出set方法,其余的可以对应写出
@Lazy
@Component
public class RedisService{
@Autowired
private RedisTemplate redisTemplate;
public void setRedisTemplate(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public boolean set(String key,Object value,int indexdb) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
快去整合自己的redis,自己造一个轮子