Redis使用之--基于Lettuce实现Spring和Redis的集成(二)


Redis和Spring的集成,不同版本,集成的实现方式存在一定的差异。可查看上一篇 《Redis使用之–基于Lettuce实现Spring和Redis的集成(一)》中有关于集成方案的背景说明,这里不再赘述。

一、集成方案

在上一篇中,介绍了spring4.x + spring-data-redis1.8.x + lettuce4.2.x环境下的集成实现方式。本篇将继续介绍另一种环境下的集成实现方式,基于spring5.x + spring-data-redis2.x + lettuce5.x环境,实现spring和redis的集成;
环境版本要求:
spring-data-redis 版本2.x
spring版本 5.x
lettuce 版本 io.lettuce 5.x
集成的实现思路和操作步骤,和上一篇的基本一致,主要是具体细节和一些版本差异上的区别;

二、集成方法

1 引入jar依赖

在项目的pom.xml文件中,分别添加spring、spring-redis-data、lettuce等jar文件的依赖

1.1 引入spring 5.x相关jar文件

这里spring使用的是5.2.2.RELEASE版本,也可以使用spring5.x的其他小版本;

<!-- Spring 依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>
1.2 引入spring-data-redis 2.x相关的jar

spring-data相关的jar文件主要有3个:

<!-- redis集成 -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-keyvalue</artifactId>
            <version>2.1.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>2.1.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
            <version>2.1.9.RELEASE</version>
        </dependency>
1.3 引入lettuce相关jar

lettuce在spring-data 2.x之后,使用的是io.lettuce.lettuce-core相关包,同时需要使用到commons-pool2,因此引入的jar文件有

<!--spring-data 2.0之后版本使用lettuce-->
        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>5.1.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.6.1</version>
        </dependency>

2 创建redis配置

2.1 添加redis.properties

在src/main/resources目录下创建一个redis.properties,主要用于配置初始化及连接redis服务的参数,具体内容如下:

### redis模式(single-单机模式, sentinel-主从哨兵模式)
redis.deploy = single

### 连接池最大连接数(使用负值表示没有限制)
lettuce.pool.maxTotal=100
### 连接池中的最大空闲连接
lettuce.pool.maxIdle=100  
### 连接池中的最小空闲连接
lettuce.pool.minIdle=50

### 单机模式地址
redis.host = 127.0.0.1
### 单机模式port
redis.port = 6379
### 单机模式密码
redis.password = 


### 哨兵模式监听的master名称
lettuce.sentinel.master=mymaster
### 哨兵模式地址列表,多个以,分割
lettuce.sentinel.nodes=127.0.0.1:26301,127.0.0.1:26302,127.0.0.1:26303
2.2 创建properties初始化类

在工程中,创建一个类,用于读取redis.properties的配置文件(也可以基于spring的@Value注解实现配置文件属性的读取)

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ResourceBundle;

/**
 * Copyright: Copyright (c) 2019 xxx有限公司
 * @ClassName: RedisProperties.java
 * @Description: Redis属性配置类
 * @version: v1.0.0
 * @author: com.tian.tblong
 * @date: 2019年10月10日 上午9:23:40 
 *
 * Modification History:
 * Date           Author          Version            Description
 *---------------------------------------------------------*
 * 2019年10月10日     com.tian.tblong           v1.0.0               新建
 */
@Component
@Data
@Slf4j
public class RedisProperties {

    private static ResourceBundle bundle;

    static {
        bundle = ResourceBundle.getBundle("redis");
        log.debug("load redis.properties and init...");
    }

    /**
     * 重新加载配置文件
     */
    public void reloadProperties(){
    	bundle = ResourceBundle.getBundle("redis");
        log.debug("reload redis.properties ...");
    }
    
    /**
     * 获取String类型配置参数
     * @param key
     * @return
     */
    public static String getString(String key) {
    	if(bundle.containsKey(key)){
    		return bundle.getString(key);
    	}
        return null;
    }
    
    /**
     * 获取Int类型配置参数
     * @param key
     * @return
     */
    public static Integer getInt(String key) {
    	String value = getString(key);
    	if(value != null && !"".equals(value.trim())){
    		return Integer.parseInt(value.trim());
    	}
        return null;
    }
    
    /**
     * 获取Boolean类型配置参数
     * @param key
     * @return
     */
    public static boolean getBoolean(String key) {
    	String value = getString(key);
    	if(value != null && !"".equals(value.trim())){
    		return Boolean.parseBoolean(value.trim());
    	}
        return false;
    }
}
2.3 创建redis属性bean

创建一个vo对象,用于将redis.properties属性中的参数封装成一个对象。代码如下:

import com.tian.tblong.prop.RedisProperties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

@Data
@Slf4j
public class RedisInfoVo {

	public RedisInfoVo(){
		getConfigResource();
	}
	
	private String deployType;
	
	private String host;
	private int port;
	private String password;
	
	private int maxTotal;
	private int maxIdle;
	private int minIdle;
	
	private String master;
    private Set<String> hosts; 
	
	public void getConfigResource(){
		loadBaseConfigInfo();     //加载基础参数配置
		loadPropEvnConfigInfo();  //加载环境参数配置
	}
	/**
	 * 加载基础参数配置
	 */
	public void loadBaseConfigInfo(){
    	int maxTotal = RedisProperties.getInt("lettuce.pool.maxTotal");
    	int maxIdle = RedisProperties.getInt("lettuce.pool.maxIdle");
    	int minIdle = RedisProperties.getInt("lettuce.pool.minIdle");

    	this.maxTotal = maxTotal;
    	this.maxIdle = maxIdle;
    	this.minIdle = minIdle;
	}
	
	/**
	 * 加载环境参数配置
	 */
	public void loadPropEvnConfigInfo(){
		String deploy = RedisProperties.getString("redis.deploy");
    	String host = RedisProperties.getString("redis.host");
    	int port = RedisProperties.getInt("redis.port");
    	String password = RedisProperties.getString("redis.password");
    	
    	String master = RedisProperties.getString("lettuce.sentinel.master");
    	String sentinelNodes = RedisProperties.getString("lettuce.sentinel.nodes");

    	this.deployType = deploy;
    	this.host = host;
    	this.port = port;
    	this.password = password;
    	
    	this.master = master;
    	
    	if(sentinelNodes != null && !"".equals(sentinelNodes.trim())){
    		String[] sentinels = sentinelNodes.split(",");
    		hosts = new HashSet<>();
        	hosts.addAll(Arrays.asList(sentinels));
    	}
    	if("single".equals(deployType)){
			log.info("load redis single conn info from properties : host->"  + this.host + ", port->" + this.port + ", password->" + this.password);
		}else if("sentinel".equals(deployType)){
			log.info("load redis sentinel conn info from properties : master->"  + this.master + ", hosts->" + sentinelNodes);
		}
	}
	
}

3 编写redis初始化配置类

创建RedisConfig.java类文件,编写redis的初始化核心配置代码:
集成代码如下:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.tian.tblong.vo.RedisInfoVo;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.lettuce.DefaultLettucePool;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;
import java.time.Duration;

import static java.util.Collections.singletonMap;

/**
 * Copyright: Copyright (c) 2019 xxx有限公司
 * @ClassName: RedisConfig.java
 * @Description: Redis换成初始化配置
 * @version: v1.0.0
 * @author: tblong
 * @date: 2019年10月10日 下午4:28:50 
 *
 * Modification History:
 * Date           Author          Version            Description
 *---------------------------------------------------------*
 * 2019年10月10日     tblong           v1.0.0               新建
 */
@Configuration
@EnableCaching // 开启缓存支持
public class RedisConfig extends CachingConfigurerSupport {

	//redis参数配置信息
	private RedisInfoVo redisVo = new RedisInfoVo();
	
	@Override
	@Bean
	public KeyGenerator keyGenerator() {
		return new KeyGenerator() {
			@Override
			public Object generate(Object target, Method method, Object... params) {
				StringBuffer sb = new StringBuffer();
				sb.append(target.getClass().getName());
				sb.append(method.getName());
				for (Object obj : params) {
					//由于参数可能不同, 缓存的key也需要不一样
					sb.append(obj.toString());
				}
				return sb.toString();
			}
		};
	}
	
	/**
	 * 缓存管理器
	 */
	@Bean
	public CacheManager cacheManager(LettuceConnectionFactory lettuceConnectionFactory) {
		/* 默认配置, 默认超时时间为30分钟=30*60s=1800s */
		RedisCacheConfiguration defaultCacheConfig
				= RedisCacheConfiguration.defaultCacheConfig()
				.entryTtl(Duration.ofSeconds(1800L))
				.disableCachingNullValues();
		RedisCacheManager.RedisCacheManagerBuilder builder
				= RedisCacheManager.builder(RedisCacheWriter.lockingRedisCacheWriter(lettuceConnectionFactory))
				.cacheDefaults(defaultCacheConfig)
				.withInitialCacheConfigurations(singletonMap("business_data",
						RedisCacheConfiguration.defaultCacheConfig()
								.entryTtl(Duration.ofSeconds(3600L))
								.disableCachingNullValues()))
				.withInitialCacheConfigurations(singletonMap("system_data",
						RedisCacheConfiguration.defaultCacheConfig()
								.entryTtl(Duration.ofSeconds(3600L))
								.disableCachingNullValues()))
				.withInitialCacheConfigurations(singletonMap("common_data",
						RedisCacheConfiguration.defaultCacheConfig()
								.entryTtl(Duration.ofSeconds(3600L))
								.disableCachingNullValues()))
				.withInitialCacheConfigurations(singletonMap("test_data",
						RedisCacheConfiguration.defaultCacheConfig()
								.entryTtl(Duration.ofSeconds(60L))
								.disableCachingNullValues()))
				.transactionAware();

		RedisCacheManager cacheManager = builder.build();

		return cacheManager;
	}
	
	/**
	 * RedisTemplate配置
	 */
	@Bean
	public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
		// 设置序列化
		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
				Object.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		om.enableDefaultTyping(DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(om);
		// 配置redisTemplate
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
		redisTemplate.setConnectionFactory(lettuceConnectionFactory);
		RedisSerializer<?> stringSerializer = new StringRedisSerializer();
		redisTemplate.setKeySerializer(stringSerializer);// key序列化
		redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// value序列化
		redisTemplate.setHashKeySerializer(stringSerializer);// Hash key序列化
		redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);// Hash value序列化
		redisTemplate.afterPropertiesSet();
		return redisTemplate;
	}

	/**
	 * @Function: RedisConfig.java
	 * @Description: 连接工厂配置
	 * @param:描述1描述
	 * @return:返回结果描述
	 * @throws:异常描述
	 *
	 * @version: v1.0.0
	 * @author: tblong
	 * @date: 2019年10月10日 上午10:40:54 
	 * Modification History:
	 * Date           Author          Version            Description
	 *---------------------------------------------------------*
	 * 2019年10月10日     tblong           v1.0.0               新建
	 */
	@Bean    
	public LettuceConnectionFactory lettuceConnectionFactory(DefaultLettucePool defaultLettucePool) {
		LettuceConnectionFactory factory = new LettuceConnectionFactory(defaultLettucePool);
		factory.setValidateConnection(true);
		return factory;
	}

	
	/**
	 * @Function: RedisConfig.java
	 * @Description: 连接池配置
	 * @param:描述1描述
	 * @return:返回结果描述
	 * @throws:异常描述
	 *
	 * @version: v1.0.0
	 * @author: tblong
	 * @date: 2019年10月10日 下午3:19:17 
	 * Modification History:
	 * Date           Author          Version            Description
	 *---------------------------------------------------------*
	 * 2019年10月10日     tblong           v1.0.0               新建
	 */
	@Bean
    public DefaultLettucePool getDefaultLettucePool(RedisSentinelConfiguration redisSentinelConfiguration, GenericObjectPoolConfig poolConfig) {
		if("single".equalsIgnoreCase(redisVo.getDeployType())){
			DefaultLettucePool defaultLettucePool = new DefaultLettucePool(redisVo.getHost(), redisVo.getPort(), poolConfig);
			if(redisVo.getPassword() != null && !"".equals(redisVo.getPassword())){
				defaultLettucePool.setPassword(redisVo.getPassword());
			}

			return defaultLettucePool;
		}else if("sentinel".equalsIgnoreCase(redisVo.getDeployType())){
			DefaultLettucePool defaultLettucePool = new DefaultLettucePool(redisSentinelConfiguration);
			defaultLettucePool.setPoolConfig(poolConfig);
			defaultLettucePool.afterPropertiesSet();
			return defaultLettucePool;
		}else{
			throw new RuntimeException("redis deploy type config error !!!, please check redis.properties.", new Throwable());
		}
		
    }
	
	/**
	 * @Function: RedisConfig.java
	 * @Description: 配置哨兵集群信息 master和host:ip
	 * @param:描述1描述
	 * @return:返回结果描述
	 * @throws:异常描述
	 *
	 * @version: v1.0.0
	 * @author: tblong
	 * @date: 2019年10月10日 上午10:25:56 
	 * Modification History:
	 * Date           Author          Version            Description
	 *---------------------------------------------------------*
	 * 2019年10月10日     tblong           v1.0.0               新建
	 */
	@Bean
	public RedisSentinelConfiguration redisSentinelConfiguration() {
		return new RedisSentinelConfiguration(redisVo.getMaster(), redisVo.getHosts());
	}

	/**
	 * @Function: RedisConfig.java
	 * @Description: 线程池配置参数设置
	 * @param:描述1描述
	 * @return:返回结果描述
	 * @throws:异常描述
	 *
	 * @version: v1.0.0
	 * @author: tblong
	 * @date: 2019年10月10日 上午10:40:22 
	 * Modification History:
	 * Date           Author          Version            Description
	 *---------------------------------------------------------*
	 * 2019年10月10日     tblong           v1.0.0               新建
	 */
	@Bean
	public GenericObjectPoolConfig genericObjectPoolConfig() {
		GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
		poolConfig.setMaxIdle(redisVo.getMaxIdle());
		poolConfig.setMinIdle(redisVo.getMinIdle());
		poolConfig.setMaxTotal(redisVo.getMaxTotal());
		//todo 其他配置        
		return poolConfig;    
	}

}

4 封装redis操作方法

在上面的步骤开发完成后,redis的集成就已经完成了。但要给业务类提供更好的redis方法使用,有必要对原生的RedisTemplate进行再次封装,提供更友好的方法给业务类使用。
创建一个RedisService方法,注入RedisTemplate,封装相关方法,代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

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

/**
 * Copyright: Copyright (c) 2019 xxx有限公司
 * @ClassName: RedisService.java
 * @Description: Redis服务入口类
 * @version: v1.0.0
 * @author: tblong
 * @date: 2019年10月28日 上午11:12:29 
 *
 * Modification History:
 * Date            Author          Version         Description
 *-------------------------------------------------------------*
 * 2019年10月28日     tblong           v1.0.0            新建
 */
@Service
public class RedisService {

	@Autowired
	RedisTemplate<String, Object> redisTemplate;

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

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

	/**
	 * 判断key是否存在
	 * 
	 * @param key  键
	 * @return true 存在 false不存在
	 */
    public boolean hasKey(String key) {
		try {
			return redisTemplate.hasKey(key);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 删除缓存
	 * 
	 * @param key 可以传一个值 或多个
	 */
    @SuppressWarnings("unchecked")
	public void del(String... key) {
		if (key != null && key.length > 0) {
			if (key.length == 1) {
				redisTemplate.delete(key[0]);
			} else {
				redisTemplate.delete(CollectionUtils.arrayToList(key));
			}
		}
	}

	/**
	 * 根据前缀删除key
	 * @param key
	 * @return
	 */
    public void delPrefix(String key) {
		// TODO Auto-generated method stub
		Set<String> keys = redisTemplate.keys(key);
		redisTemplate.delete(keys);
	}

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

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

	/**
	 * 普通缓存放入并设置时间
	 * 
	 * @param key 键
	 * @param value 值
	 * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
	 * @return true成功 false 失败
	 */
    public 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) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 递增
	 * 
	 * @param key 键
	 * @param delta 要增加几(大于0)
	 * @return
	 */
    public long incr(String key, long delta) {
		if (delta < 0) {
			throw new RuntimeException("递增因子必须大于0");
		}
		return redisTemplate.opsForValue().increment(key, delta);
	}

	/**
	 * 递减
	 * 
	 * @param key 键
	 * @param delta 要减少几(小于0)
	 * @return
	 */
    public long decr(String key, long delta) {
		if (delta < 0) {
			throw new RuntimeException("递减因子必须大于0");
		}
		return redisTemplate.opsForValue().increment(key, -delta);
	}
	
	/**
	 * 通过前缀获取储存在redis中的value
	 * @param prefix
	 * @return
	 */
    public Set<String> getByPrefix(String prefix) {
		// TODO Auto-generated method stub
		return redisTemplate.keys(prefix+"*");
	}

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

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

	/**
	 * HashSet
	 * 
	 * @param key 键
	 * @param map 对应多个键值
	 * @return true 成功 false 失败
	 */
    public boolean hmset(String key, Map<String, Object> map) {
		try {
			redisTemplate.opsForHash().putAll(key, map);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * HashSet 并设置时间
	 * 
	 * @param key 键
	 * @param map 对应多个键值
	 * @param time 时间(秒)
	 * @return true成功 false失败
	 */
    public boolean hmset(String key, Map<String, Object> map, long time) {
		try {
			redisTemplate.opsForHash().putAll(key, map);
			if (time > 0) {

				expire(key, time);
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

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

	/**
	 * 向一张hash表中放入数据,如果不存在将创建
	 * 
	 * @param key 键
	 * @param item 项
	 * @param value 值
	 * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
	 * @return true 成功 false失败
	 */
    public 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) {
			e.printStackTrace();
			return false;
		}
	}

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

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

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

	// ============================set=============================
	/**
	 * 根据key获取Set中的所有值
	 * 
	 * @param key 键
	 * @return
	 */
    public Set<Object> sGet(String key) {
		try {
			return redisTemplate.opsForSet().members(key);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

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

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

	/**
	 * 将set数据放入缓存
	 * 
	 * @param key 键
	 * @param time 时间(秒)
	 * @param values 值 可以是多个
	 * @return 成功个数
	 */
    public 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) {
			e.printStackTrace();
			return 0;
		}
	}

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

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

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

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

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

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

	/**
	 * 将list放入缓存
	 * 
	 * @param key 键
	 * @param value 值
	 * @param time 时间(秒)
	 * @return
	 */
    public 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) {
			e.printStackTrace();
			return false;
		}
	}

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

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

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

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

}

5 验证

完成集成代码的开发后,使用一个单元测试方法,即可验证集成是否成功,简单的测试方法如下:

	@Test
    public void startRedis(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(InitConfiguretion.class);

        RedisService redisService = (RedisService) applicationContext.getBean("redisService");
        if(redisService != null){
            redisService.set("EFG", "987654");
            System.out.println("----->" + redisService.get("EFG"));
        }
    }

InitConfiguretion类的主要作用,是在类上面添加一个@ComponentScan(basePackages = “com”)自动扫描包的注解,让集成的代码初始化时加入到spring IOC容器中管理;
单元测试打印结果如下:
在这里插入图片描述

三、总结

通过两篇文章,介绍了两种不同版本环境的集成方式,总体上的集成思路和步骤都是一致的。不同的地方在于CacheManager的配置及jar文件版本的区别。
这两篇redis的集成,都是基于和spring框架的环境搭建。在当前技术趋势下,大部分项目都使用到了springboot框架,基于springboot+redis的集成,就要相对简单。后续抽空再进行介绍。
本文的源码地址已上传到github,有需要的可以下载源码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值