1、父pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.java.ashare</groupId>
<artifactId>JavaAction</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>JavaAction</name>
<description>JavaAction</description>
<modules>
<!-- spring boot redis集成 -->
<module>SpringBootRedis</module>
</modules>
<properties>
<java.version>1.8</java.version>
</properties>
<!-- spring boot启动父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
–
2、子pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.java.ashare</groupId>
<artifactId>JavaAction</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>SpringBootRedis</artifactId>
<name>SpringBootRedis</name>
<description>SpringBootRedis</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.java.ashare.config.client.ConfigClientApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
注意:springboot2之后默认使用lettuce操作redis,所以这里需要单独引入jedis。
3、Jedis单独实战
package com.java.ashare.redis.clients.jedis;
import java.util.Date;
import java.util.HashMap;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisPubSub;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Transaction;
/**
* jedis入门实战
*/
public class JedisApplication {
public static void main(String[] args) {
// jedis连接池配置,JedisPoolConfig继承GenericObjectPoolConfig
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(20); // -1: 表示不限制
jedisPoolConfig.setMaxIdle(20);
jedisPoolConfig.setMinIdle(0);
jedisPoolConfig.setMaxWaitMillis(60000);
jedisPoolConfig.setTestOnBorrow(true);
jedisPoolConfig.setTestOnReturn(true);
jedisPoolConfig.setTestWhileIdle(true);
// 创建连接池 【redis单机】
// new JedisPool(poolConfig, host, port, timeout, password, database);
// 提供不同构造方法满足不同情况,根据情况选择合适的构造方法
JedisPool jedisPool = new JedisPool(jedisPoolConfig, "192.168.78.169", 6379);
// 创建连接池 【redis-sentinel哨兵模式高可用】
// 添加sentinel节点
/*
Set<String> sentinels = new HashSet<String>();
sentinels.add(new HostAndPort("192.168.78.169", 26379).toString());
sentinels.add(new HostAndPort("192.168.78.169", 26380).toString());
sentinels.add(new HostAndPort("192.168.78.169", 26381).toString());
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool("mymaster", sentinels, jedisPoolConfig);
Jedis jedis = jedisSentinelPool.getResource();
*/
// 创建连接池 【redis-cluster集群模式】
// 添加所有主从节点
/*
Set<HostAndPort> nodes = new HashSet<HostAndPort>();
nodes.add(new HostAndPort("192.168.78.169", 6379));
nodes.add(new HostAndPort("192.168.78.169", 6380));
nodes.add(new HostAndPort("192.168.78.169", 6381));
nodes.add(new HostAndPort("192.168.78.169", 6382));
nodes.add(new HostAndPort("192.168.78.169", 6383));
nodes.add(new HostAndPort("192.168.78.169", 6384));
JedisCluster jedisCluster = new JedisCluster(nodes, jedisPoolConfig);
jedisCluster.set("key", "value"); // 直接使用jedisCluster实例操作
*/
Jedis jedis = null;
try {
// 获取连接
jedis = jedisPool.getResource();
// 基本操作
jedis.del("key");
jedis.del("key", "key1");
jedis.expire("key", 60);
jedis.expireAt("key", new Date().getTime());
jedis.persist("key"); // 设置key永不过期
jedis.exists("key");
jedis.exists("key", "key1");
jedis.dbSize(); // 当前数据库key个数,包含过期key
jedis.flushDB(); // 清空当前数据库
jedis.flushAll(); // 清空当前实例,所有库
jedis.select(0); // 切换数据库
jedis.keys("pattern"); // 返回匹配pattern的有效key
jedis.scan("cursor"); // 生成环境禁用keys,使用scan迭代
// 字符串操作
jedis.set("key", "value");
jedis.mset("key", "value", "key1", "value1");
jedis.setnx("key", "value");
jedis.set("key", "value", "nx"); // nx: 当key不存在时才设置;xx: 当key存在才设置
jedis.setex("key", 60, "value"); // 60: 设置过期时间60s
jedis.set("key", "value", "nx", "ex", 60); // ex: seconds秒;px: milliseconds毫秒,分布式锁场景下setnx+expire合并,保证原子性
jedis.get("key");
jedis.mget("key", "key1");
jedis.incr("key");
jedis.incrBy("key", 10);
jedis.decr("key");
jedis.decrBy("key", 10);
// 哈希操作
jedis.hset("key", "field", "value");
jedis.hsetnx("key", "field", "value");
jedis.hmset("key", new HashMap<String, String>());
jedis.hget("key", "field");
jedis.hmget("key", "field", "field1");
jedis.hgetAll("key");
jedis.hexists("key", "field");
jedis.hdel("key", "field", "field1");
jedis.hlen("key");
jedis.hincrBy("key", "field", 1);
jedis.hincrByFloat("key", "field", 1.1);
// 列表操作
jedis.lpush("key", "string", "string1");
jedis.rpush("key", "string", "string1");
jedis.lpop("key");
jedis.rpop("key");
jedis.blpop(60, "key"); // 0: 表示一直阻塞
jedis.brpop(60, "key");
jedis.lrange("key", 0, 10); // start或end为负数时表示从列表后面获取数据,如-1表示最后一个数据,-2表示倒数第二个数据
jedis.llen("key");
// 集合操作
jedis.sadd("key", "member", "member1");
jedis.srem("key", "member", "member1");
jedis.smembers("key");
jedis.scard("key");
jedis.sismember("key", "member");
jedis.srandmember("key"); // 随机返回1个成员
jedis.srandmember("key", 10); // 随机返回10个成员
jedis.spop("key"); // 随机弹出1个成员
jedis.spop("key", 10); // 随机弹出10个成员
jedis.sinter("key", "key1");
jedis.sinterstore("dstkey", "key", "key1");
jedis.sunion("key", "key1");
jedis.sunionstore("dstkey", "key", "key1");
jedis.sdiff("key", "key1");
jedis.sdiffstore("dstkey", "key", "key1");
// 有序集合操作
jedis.zadd("key", 80, "member");
jedis.zadd("key", new HashMap<String, Double>());
jedis.zcard("key");
jedis.zcount("key", 0, 100);
jedis.zrank("key", "member");
jedis.zrevrank("key", "member");
jedis.zrange("key", 0, 10);
jedis.zrevrange("key", 0, 10);
jedis.zscore("key", "member");
jedis.zinterstore("dstkey", "set", "set1");
jedis.zunionstore("dstkey", "set", "set1");
// ...等等
// 事务
jedis.watch("key", "key1");
Transaction transaction = jedis.multi();
transaction.exec();
transaction.discard();
// pub/sub
jedis.subscribe(new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
System.out.println("channel: " + channel + ", message: " + message);
}
}, "channel", "channel1");
jedis.publish("channel", "message");
// pipeline
Pipeline pipeline = jedis.pipelined();
for(int i = 0; i < 10000; i++) {
pipeline.set("key", "value");
}
// 只执行同步但不返回结果
pipeline.sync();
// 同步并返回结果
pipeline.syncAndReturnAll();
} finally {
if(jedis != null) {
// 记住:关闭jedis要放在finally块中,如果使用连接池则归还连接给连接池,如果使用单实例则直接关闭连接
jedis.close();
}
}
}
}
4、Jedis+SpringBoot实战
【--------------------------------单机--------------------------------】
application.yml
spring:
redis:
host: 192.168.78.169
port: 6379
# password: 123456
database: 0
timeout: 60000
jedis:
pool:
maxActive: 15
maxIdle: 15
minIdle: 0
maxWait: 30000
FastJsonRedisSerializer.java
package com.java.ashare.redis.config;
import java.nio.charset.Charset;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import com.alibaba.fastjson.JSON;
public class FastJsonRedisSerializer implements RedisSerializer<Object> {
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
@Override
public byte[] serialize(Object t) throws SerializationException {
if (t == null) {
return null;
}
return JSON.toJSONStringWithDateFormat(t, DATE_FORMAT).getBytes(DEFAULT_CHARSET);
}
@Override
public Object deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
return new String(bytes, DEFAULT_CHARSET);
}
}
RedisConfig.java
package com.java.ashare.redis.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
// key使用字符串序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
// value使用fastjson序列化,fastjson比jackson速度快
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer();
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
// redisConnectionFactory为JedisConnectionFactory,自动注入进来
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}
RedisUtil.java
package com.java.ashare.redis.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
/**
* 一、redis自动配置类:RedisRepositoriesAutoConfiguration,可以查看到能配置的属性以及可以使用的bean
* RedisRepositoriesAutoConfiguration源码可知:
* 提供了RedisTemplate<Object, Object>和StringRedisTemplate两种RedisTemplate的bean
* 区别:
* RedisTemplate<Object, Object>
* keySerializer、valueSerializer、hashKeySerializer、hashValueSerializer
* 使用JdkSerializationRedisSerializer做序列化,用redis客户端查看key-value时显示一串十六进制的字符串,可读性很差
* 泛型是<Object, Object>,写代码不方便,需要写好多类型转换的代码,不推荐
*
* StringRedisTemplate
* 使用StringRedisSerializer做序列化,用redis客户端查看key-value时显示正常的字符串,缺点是key、value必须都是字符串
* 如果是对象的话,需要在程序中手动把对象数据转化为json字符串(fastjson)
*
* 综上:我们可以自定义bean---RedisTemplate<String, Object>,查看config/RedisConfig
*
*
* 二、RedisConnectionFactory实现LettuceConnectionFactory、JedisConnectionFactory
* springboot1.x默认使用JedisConnectionFactory
* springboot2.x默认使用LettuceConnectionFactory,可以通过debug调试查看变量可知
*/
@Component
public class RedisUtil {
// 自定义redisTemplate
private static RedisTemplate<String, Object> redisTemplate;
// 使用springboot提供的stringRedisTemplate
// private static StringRedisTemplate stringRedisTemplate;
/**
* 通过set方法注入redisTemplate(针对静态变量)
*/
@Autowired
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
RedisUtil.redisTemplate = redisTemplate;
}
/*@Autowired
public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
RedisUtil.stringRedisTemplate = stringRedisTemplate;
}*/
/**
* 获取string操作对象
*/
public static ValueOperations<String, Object> valueOperations() {
return RedisUtil.redisTemplate.opsForValue();
}
/**
* 获取hash操作对象
*/
public static HashOperations<String, String, Object> hashOperations() {
return RedisUtil.redisTemplate.opsForHash();
}
/**
* 获取list操作对象
*/
public static ListOperations<String, Object> listOperations() {
return RedisUtil.redisTemplate.opsForList();
}
/**
* 获取set操作对象
*/
public static SetOperations<String, Object> setOperations() {
return RedisUtil.redisTemplate.opsForSet();
}
/**
* 获取zset操作对象
*/
public static ZSetOperations<String, Object> zSetOperations() {
return RedisUtil.redisTemplate.opsForZSet();
}
}
RedisApplication.java
package com.java.ashare.redis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.java.ashare.redis.utils.RedisUtil;
@SpringBootApplication
public class RedisApplication {
public static void main(String[] args) {
SpringApplication.run(RedisApplication.class, args);
RedisUtil.valueOperations().set("k1", "v1");
System.out.println("k1: " + RedisUtil.valueOperations().get("k1"));
}
}
【--------------------------------sentinel哨兵模式--------------------------------】
在【单机】上做如下修改:
application.yml
spring:
redis:
database: 0
timeout: 60000
# password: 123456
jedis:
pool:
maxActive: 15
maxIdle: 15
minIdle: 0
maxWait: 60000
sentinel:
master: mymaster
nodes: 192.168.78.169:26379,192.168.78.169:26380,192.168.78.169:26381
RedisConfig.java
package com.java.ashare.redis.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
// key使用字符串序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
// value使用fastjson序列化,fastjson比jackson速度快
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer();
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
// redisConnectionFactory为JedisConnectionFactory,自动注入进来,也可以自定义@Bean(JedisConnectionFactory)覆盖springboot默认的值
// debug查看redisTemplate中变量clientConfiguration、configuration可知yml配置信息注入进来
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}
【--------------------------------cluster集群模式--------------------------------】
在【单机】上做如下修改:
application.yml
spring:
redis:
database: 0
timeout: 60000
# password: 123456
jedis:
pool:
maxActive: 15
maxIdle: 15
minIdle: 0
maxWait: 60000
cluster:
nodes:
- 192.168.78.169:6379
- 192.168.78.169:6380
- 192.168.78.169:6381
- 192.168.78.169:6382
- 192.168.78.169:6383
- 192.168.78.169:6384
JedisConnectionFactory说明
1、可以直接使用springboot提供的默认JedisConnectionFactory;
2、自定义@Bean,可以查看JedisConnectionFactory的构造函数,针对变量RedisConfiguration有三种情况:
- RedisStandaloneConfiguration对应单机;
- RedisSentinelConfiguration对应sentinel哨兵模式;
- RedisClusterConfiguration对应集群模式;