1. Redis的安装
为了方便学习,使用 Windows 系统对 Redis 进行讲解。由于 Redis 官方没有提供 Windows 版的安装包,但可以从GitHub 中来下载 Windows 版 Redis 安装包,下载:点击前往【https://github.com/tporadowski/redis/releases】。
注意:Windows 安装包是某位“大神”根据 Redis 源码改造的,并非 Redis 官方提供。
进入 GitHub 的下载页面,Redis 支持 32 位和 64 位的 Window 系统,大家根据个人情况自行下载:
下载完成后,解压放入指定文件夹下(无需安装,解压即可),看到如下文件结构:
启动 redis-server 服务程序:
使用命令:> redis-server.exe redis.windows.conf
用 redis-cli 客户端连接:
完整命令:
redis-cli.exe -h 127.0.0.1 -a 'xxx' -p 6379
- -h 表示redis服务器的 IP地址
- -a 表示输入密码
- -p 表示 redis服务器的端口
示例中设置了键值对 set myKey abc,并且读取也成功了。说明 Redis 安装成功。
2. SpringBoot整合Redis
SpringBoot 版本 2.1.8.RELEASE
2.1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--reids版本为1.4.1版本以上需要添加-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
使用 lettuce 必须 导入 commons-pool2 包,否则在启动 SpringBoot项目时会报错。
2.2 单机版 application.yml 文件配置
server:
port: 8080
spring:
redis:
database: 0
port: 6379
host: localhost
password:
lettuce:
pool:
# 连接池最大连接数(使用负值表示没有限制)
max-active: 1024
# 连接分配在池耗尽之前在抛出异常之前应阻止的最大时间量(连接池最大阻塞等待时间以毫秒为单位) 使用负值无限期地阻止
max-wait: -1
# 连接池中的最大空闲连接, 使用负值来表示无限数量的空闲连接
max-idle: 200
# 连接池中的最小空闲连接, 此设置只有在正值时才有效果
min-idle: 5
# 连接超时时间(毫秒)
timeout: 30000
注:redis 数据源连接池的配置有所不同,jedis、lettuce。在 SpringBoot2 之后,默认就使用 lettuce了
不使用 jedis的原因?
jedis是比较优秀的框架,但有一些线程不安全的问题。在 lettuce 下得到了很好的解决,,lettuce 集成了 Netty IO 性能得到了保证及线程安全。
2.3 编写Redis核心配置类
// @Configuration注解 通常与@bean结合使用,当@bean注解到方法上,代表将该方法做为一个bean交给了spring容器管理
@Configuration
public class RedisConfig {
// 表示创建 redisTemplate Bean
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
/**
* redis默认使用 JDK序列化, 优点在反序列化时不需要声明class, 但序列化的数据是json的5倍大小, 这样就比较消耗redis的内存, 所以一般会重写 redis的序列化。
*
* spring提供的序列化器:
* Jackson2JsonRedisSerializer
* JdkSerializationRedisSerializer
* OxmSerializer
* StringRedisSerializer
* GenericToStringRedisSerializer
* GenericJackson2JsonRedisSerializer
**/
// 使用 Jackson2JsonRedisSerializer 序列化器, 将对象解析成可以序列化的对象
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
// 使用Mapper对象进行转义
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//开始序列化对象
jackson2JsonRedisSerializer.setObjectMapper(om);
// String 的序列化器
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 设置 key 的序列化器为 StringRedisSerializer
template.setKeySerializer(stringRedisSerializer);
// 设置 hash key 的序列化器为 StringRedisSerializer
template.setHashKeySerializer(stringRedisSerializer);
// 设置 value 的序列化器为 Jackson2JsonRedisSerializer
template.setValueSerializer(jackson2JsonRedisSerializer);
// 设置 hash value 的序列化器为 Jackson2JsonRedisSerializer
template.setHashKeySerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
redis默认使用 JDK序列化,优点在反序列化时不需要声明class,但序列化后的数据是json的5倍大小,这样就比较消耗redis的内存,所以我们一般会重写 redis的序列化。
Spring提供常用的序列化器:
- Jackson2JsonRedisSerializer
- JdkSerializationRedisSerializer
- StringRedisSerializer
- GenericToStringRedisSerializer
- GenericJackson2JsonRedisSerializer
关于序列化器也可以自定义实现,我们只需要实现
RedisSerializer<T>
接口即可。具体见下一次 自定义序列化器的实现。
2.4 编写 Redis工具类
@Component
public class RedisUtil {
// 为了解决 静态属性变量的注入, 只能使用 ApplicationContext.getBean()的模式
@SuppressWarnings("unchecked")
private static RedisTemplate<String, Object> redisTemplate = AppContextHolder.getBean("redisTemplate", RedisTemplate.class);
/**
* 设置有效时间, 默认秒
*/
public static boolean expire(final String key, final long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置有效时间
*/
public static boolean expire(final String key, final long timeout, final TimeUnit unit) {
Boolean ret = redisTemplate.expire(key, timeout, unit);
return ret != null && ret;
}
/**
* 删除单个key
*/
public static boolean del(final String key) {
Boolean ret = redisTemplate.delete(key);
return ret != null && ret;
}
/**
* 删除多个key
*/
public static long del(final Collection<String> keys) {
Long ret = redisTemplate.delete(keys);
return ret == null ? 0 : ret;
}
/**
* 存入普通对象
*/
public static void set(final String key, final Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 存入普通对象
*/
public static void set(final String key, final Object value, final long timeout) {
redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}
/**
* 获取普通对象
*/
public static Object get(final String key) {
return redisTemplate.opsForValue().get(key);
}
/** -------------------Hash相关操作--------------------- */
/**
* 往Hash中存入数据
*/
public static void hPut(final String key, final String filed, final Object value) {
redisTemplate.opsForHash().put(key, filed, value);
}
/**
* 往Hash中存入多个数据
*/
public static void hPutAll(final String key, final Map<String, Object> filedMap) {
redisTemplate.opsForHash().putAll(key, filedMap);
}
/**
* 获取Hash中的数据
*/
public static Object hGet(final String key, final String filed) {
return redisTemplate.opsForHash().get(key, filed);
}
/**
* 获取多个Hash中的数据
*/
public static List<Object> hMultiGet(final String key, final Collection<Object> fileds) {
return redisTemplate.opsForHash().multiGet(key, fileds);
}
/** -------------------Set相关操作--------------------- */
/**
* 往Set中存入数据
*/
public static long sSet(final String key, final Object... values) {
Long count = redisTemplate.opsForSet().add(key, values);
return count == null ? 0 : count;
}
/**
* 删除Set中的数据
*/
public static long sDel(final String key, final Object... values) {
Long count = redisTemplate.opsForSet().remove(key, values);
return count == null ? 0 : count;
}
/** -------------------List相关操作--------------------- */
/**
* 往List左侧中存入数据
*/
public static long lPush(final String key, final Object value) {
Long count = redisTemplate.opsForList().leftPush(key, value);
return count == null ? 0 : count;
}
/**
* 往List右侧中存入数据
*/
public static long rPush(final String key, final Object value) {
Long count = redisTemplate.opsForList().rightPush(key, value);
return count == null ? 0 : count;
}
/**
* 往List中左侧存入多个数据
*/
public static long lPushAll(final String key, final Collection<Object> values) {
Long count = redisTemplate.opsForList().leftPushAll(key, values);
return count == null ? 0 : count;
}
/**
* 往List中左侧存入多个数据
*/
public static long lPushAll(final String key, final Object... values) {
Long count = redisTemplate.opsForList().leftPushAll(key, values);
return count == null ? 0 : count;
}
/**
* 往List中右侧存入多个数据
*/
public static long rPushAll(final String key, final Collection<Object> values) {
Long count = redisTemplate.opsForList().rightPushAll(key, values);
return count == null ? 0 : count;
}
/**
* 往List中右侧存入多个数据
*/
public static long rPushAll(final String key, final Object... values) {
Long count = redisTemplate.opsForList().rightPushAll(key, values);
return count == null ? 0 : count;
}
/**
* 从List中获取begin到end之间的元素
*/
public static List<Object> listGetRange(final String key, final int start, final int end) {
return redisTemplate.opsForList().range(key, start, end);
}
/**
* 从List左侧弹出数据
*/
public static Object listGetL(final String key) {
return redisTemplate.opsForList().leftPop(key);
}
/**
* 从List右侧弹出数据
*/
public static Object listGetR(final String key) {
return redisTemplate.opsForList().rightPop(key);
}
}
2.5 启动及测试
@RestController
@SpringBootApplication
public class SpringRedisApplication {
// 存储 实体类
@RequestMapping(value="/set", method=RequestMethod.GET)
public String hello(){
Account acc = new Account();
acc.setId(3);
acc.setUserId("admin");
acc.setMoney(100);
RedisUtil.set("admin", acc);
return "ok";
}
@RequestMapping(value="/get", method=RequestMethod.GET)
public String load(){
Account acc = (Account)RedisUtil.get("admin");
return acc.toString();
}
// 存储 字符串类型
@RequestMapping(value="/setString", method=RequestMethod.GET)
public String putString(@RequestParam(value="name") String name) {
Integer c = 1;
Object obj = RedisUtil.get("user:uid:" + name);
if(obj != null) {
c = 1 + (Integer)obj;
}
RedisUtil.set("user:uid:" + name , c);
return "login number: " + c;
}
public static void main(String[] args) {
SpringApplication.run(SpringRedisApplication.class, args);
}
}
通过浏览器访问进行操作
总结
以上是使用 SpringBoot 的 RedisTemplate
模板,实现了单机版的 Redis 操作。下一步计划讲解 Redis的 哨兵模式、集群模式 以及 pub/sub模式的使用。
想要源码可以私信