因为我使用的是 java ,所以我学习的是java 的客户端 :Jredis 。整合结合自己的项目,把 Jredis 的客户端整合一下。
我们整合需要的工具:
1. Redis Service
2. redis.clients.jedis 2.9.0 (java 客户端链接redis)
3. org.springframework.data.spring-data-redis 1.6.2.RELEASE (spring 整合的 jedis)
4. jackson-core;jackson-databind ;jackson-annotations (序列化用)
这里 spring-data-redis 和 jedis 都是用的最新版本的,但两个版本不是很兼容,最后经过测试 jedis 2.9.0 和 spring-data-redis 1.6.2 不会报错。
整合的所需的jar 包
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.8</version>
</dependency>
设置链接 Redis 的配置文件
我这里参考官网的:https://docs.spring.io/spring-data/redis/docs/1.8.18.RELEASE/reference/html/#redis:connectors:jredis注:高版本的 spring-data-redis 推荐使用 Lettuce 链接 redis-service,使用的Netty。当然高版本的也会给你自己选择,使用那种方式链接。这里我们使用Jredis来链接。
增加 redis.properties 配置的参数,密码和ip换成自己的
#JedisPoolConfig的参数
#最大连接数
redis.pool.maxTotal=100
#最大空闲时间
redis.pool.maxIdle=10
#每次最大连接数
redis.pool.numTestsPerEvictionRun=1024
#释放扫描的扫描间隔
redis.pool.timeBetweenEvictionRunsMillis=30000
#连接的最小空闲时间
redis.pool.minEvictableIdleTimeMillis=1800000
#连接控歘按时间多久后释放,当空闲时间>该值且空闲连接>最大空闲连接数时直接释放
redis.pool.softMinEvictableIdleTimeMillis=10000
#获得链接时的最大等待毫秒数,小于0:阻塞不确定时间,默认-1
redis.pool.maxWaitMillis=1500
#在获得链接的时候检查有效性,默认false
redis.pool.testOnBorrow=true
#在空闲时检查有效性,默认false
redis.pool.testWhileIdle=true
#连接耗尽时是否阻塞,false报异常,true阻塞超时,默认true
redis.pool.blockWhenExhausted=false
#JedisConnectionFactory的参数
#主机地址,默认:localhost
redis.hostName=localhost
#主机端口,默认:6379
redis.port=6379
#超时时间,默认:2000
redis.timeout=3000
#密码
redis.password=123456
#是否使用连接池,默认true
redis.usePool=true
#使用数据库的索引,0-15之间的数字,默认:0
redis.dbIndex=0
#是否使用数据类型的转换,默认:true
#redis.convertPipelineAndTxResults
#哨兵配置
#redis.sentinelConfig
#集群配置
#redis.clusterConfig
配置 springBean,创建 RedisConfig
@Data
@Configuration
@PropertySource("classpath:redis.properties")
public class RedisConfig {
@Value("${redis.pool.maxTotal}")
private int maxTotal;
@Value("${redis.pool.maxIdle}")
private int maxIdle;
@Value("${redis.pool.numTestsPerEvictionRun}")
private int numTestsPerEvictionRun;
@Value("${redis.pool.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${redis.pool.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${redis.pool.softMinEvictableIdleTimeMillis}")
private int softMinEvictableIdleTimeMillis;
@Value("${redis.pool.maxWaitMillis}")
private int maxWaitMillis;
@Value("${redis.pool.testOnBorrow}")
private boolean testOnBorrow;
@Value("${redis.pool.testWhileIdle}")
private boolean testWhileIdle;
@Value("${redis.pool.blockWhenExhausted}")
private boolean blockWhenExhausted;
@Value("${redis.hostName}")
private String hostName;
@Value("${redis.port}")
private int port;
@Value("${redis.timeout}")
private int timeout;
@Value("${redis.password}")
private String password;
@Value("${redis.dbIndex}")
private int dbIndex;
@Value("${redis.usePool}")
private boolean usePool;
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory config = new JedisConnectionFactory();
//设置链接的基本信息
config.setHostName(hostName);
config.setPort(port);
config.setTimeout(timeout);
config.setPassword(password);
config.setDatabase(dbIndex);
config.setUsePool(usePool);
//设置链接池的信息
config.getPoolConfig().setMaxTotal(maxTotal);
config.getPoolConfig().setMaxIdle(maxIdle);
config.getPoolConfig().setNumTestsPerEvictionRun(numTestsPerEvictionRun);
config.getPoolConfig().setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
config.getPoolConfig().setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
config.getPoolConfig().setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis);
config.getPoolConfig().setMaxWaitMillis(maxWaitMillis);
config.getPoolConfig().setTestOnBorrow(testOnBorrow);
config.getPoolConfig().setTestWhileIdle(testWhileIdle);
config.getPoolConfig().setBlockWhenExhausted(blockWhenExhausted);
return config;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory jedisConnectionFactory){
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(jedisConnectionFactory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSeial.setObjectMapper(om);
// 值采用json序列化
template.setValueSerializer(jacksonSeial);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
// 设置hash key 和value序列化模式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jacksonSeial);
template.afterPropertiesSet();
return template;
}
}
最后在Action 中进行操作。
@RequestMapping("/redis")
@RestController
@Slf4j
public class RedisTest {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@RequestMapping("/index.do")
public String redisIndex(){
// String
log.info("========== String ==========");
redisTemplate.opsForValue().set("hello","world");
String returnStr = (String) redisTemplate.opsForValue().get("hello");
log.info(returnStr);
// Hash
log.info("========== Hash ==========");
redisTemplate.opsForHash().put("user:1:info","name","小明");
redisTemplate.opsForHash().put("user:1:info","age","26");
String name = (String) redisTemplate.opsForHash().get("user:1:info","name");
String age = (String) redisTemplate.opsForHash().get("user:1:info","age");
log.info("name = {};age = {}",name,age);
// List
log.info("========== List ==========");
redisTemplate.opsForList().rightPush("mylist","A");
redisTemplate.opsForList().rightPush("mylist","B");
redisTemplate.opsForList().rightPush("mylist","C");
List<Object> listStr = redisTemplate.opsForList().range("mylist",0,-1);
for (Object object : listStr){
log.info(object.toString());
}
redisTemplate.opsForList().remove("mylist",0,-1);
// set
log.info("========== Set ==========");
redisTemplate.opsForSet().add("myset1","A","B","C");
redisTemplate.opsForSet().add("myset2","B","C","D");
//求并集
Set<Object> setStr = redisTemplate.opsForSet().union("myset1","myset2");
for (Object object : setStr){
log.info(object.toString());
}
// zset
log.info("========== zset ==========");
redisTemplate.opsForZSet().add("myzset","xiaoming",56);
redisTemplate.opsForZSet().add("myzset","xiaohua",66);
redisTemplate.opsForZSet().add("myzset","xiaowang",98);
Set<ZSetOperations.TypedTuple<Object>> zsetStr = redisTemplate.opsForZSet().rangeWithScores("myzset",0,-1);
Iterator<ZSetOperations.TypedTuple<Object>> iterator = zsetStr.iterator();
while(iterator.hasNext()) {
ZSetOperations.TypedTuple<Object> next = iterator.next();
log.info("value:{} === score:{}", next.getValue(), next.getScore());
}
return "";
}
}
执行结果
========== String ==========
world
========== Hash ==========
name = 小明;age = 26
========== List ==========
A
B
C
========== Set ==========
A
C
B
D
========== zset ==========
value:xiaoming === score:56.0
value:xiaohua === score:66.0
value:xiaowang === score:98.0
总结
从上面整体来看,和 redis-cli 上面使用的命令差不多。但是下面还是有几个注意的点。
1:我刚刚开始学习 搞不清楚 jredis 和 RedisTemplate 有什么区别,后面经查询 Jredis是
redis.clients.jedis 2.9.0 包的,RedisTemplate 是spring 封装了 jedis 的操作。
2:之前看教程和视频 user:1:info 这种,以为至少好识别,但是看RedisDeskopManage 的里面,也是按照 :来进行分层的,很好辨识。存在即合理啊。
(CSDN 上面RedisDeskopManage (windows版) 工具要积分:https://pan.baidu.com/s/1v7TwNrZLYrKJcNYmBckrYw 提取码:4nua)
3:jedis 和 spring-data-redis 的版本要合适。
4:要进行序列化,不然图形界面里面的内容会乱码不好观察,包括英文。
5:看着别人说的头头是道,还是自己实践一下。还是会发现很多问题,印象也会深刻。