SpringBoot整合Redis——两种方式(Jedis、RedisTemplate)

前言

redis是一种nosql数据库,以<key,value>的形式存储数据,其速度相比于MySQL之类的数据库,相当于内存读写与硬盘读写的差别,所以常常用作缓存。接下来就分别看看在springboot项目中如何使用redis

本篇基于SpringBoot + Redis实现数据缓存以及分库存储,首先我们要知道,SpringBoot整合Redis有两种方式,分别是Jedis和RedisTemplate,这两者有何区别?

Jedis是Redis官方推荐的面向Java的操作Redis的客户端,而RedisTemplate是SpringDataRedis中对JedisApi的高度封装。其实在SpringBoot的官网上我们也能看到,官方现在推荐的是SpringDataRedis形式,相对于Jedis来说可以方便地更换Redis的Java客户端,其比Jedis多了自动管理连接池的特性,方便与其他Spring框架进行搭配使用如:SpringCache。


SpringBoot 整合Redis(Jedis)

具体分为:添加依赖+redis配置信息+JedisPool工厂+RedisService(包含序列化)

添加依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.1.0</version>
</dependency>

<!-- 用来序列化的 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>

redis配置信息

经常用到的参数
# 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方法
}

JedisPool工厂

@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

RedisService

我这里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 <T>
     * @return
     */
    public <T> T get(KeyPrefix prefix,String key,Class<T> 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 <T>
     * @return
     */
    public <T> 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 <T>
     * @return
     */
    public <T> 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 <T>
     * @return
     */
    public <T> 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 <T>
     * @return
     */
    public <T> 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 <T> 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> T stringToBean(String str,Class<T> 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();
        }
    }



}

SpringBoot 整合Redis(RedisTemplate)

具体分为:添加依赖+redis配置信息+RedisTemplate+序列化+RedisService

添加依赖

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>${redis.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-redis</artifactId>
	<version>${spring.redis.version}</version>
</dependency>

redis配置信息

#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服务器地址、连接端口、连接密码

RedisTemplate

@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<Object>(Object.class);
    }
 
    /**
     * @auther: zhangyingqi
     * @date: 17:51 2018/8/28
     * @param: [redisTemplate, factory]
     * @return: void
     * @Description: 设置数据存入 redis 的序列化方式,并开启事务
     */
    private void initDomainRedisTemplate(RedisTemplate redisTemplate, RedisConnectionFactory factory) {
        //如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setValueSerializer(fastJson2JsonRedisSerializer());
        // 开启事务
        redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.setConnectionFactory(factory);
    }
 
    /**
     * @auther: zhangyingqi
     * @date: 17:51 2018/8/28
     * @param: [redisTemplate]
     * @return: com.springboot.demo.base.utils.RedisUtil
     * @Description: 注入封装RedisTemplate
     */
    @Bean(name = "redisUtil")
    public RedisUtil redisUtil(RedisTemplate redisTemplate) {
        log.info("RedisUtil注入成功!");
        RedisUtil redisUtil = new RedisUtil();
        redisUtil.setRedisTemplate(redisTemplate);
        return redisUtil;
    }
 
}

在这里就得到了一个RedisTemplate的Bean

序列化

引入自定义序列化,防止特殊情况报错

public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
 
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
 
    private Class<T> clazz;
 
    public FastJson2JsonRedisSerializer(Class<T> 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);
    }
}

RedisService

在这里我只给出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,自己造一个轮子

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值