technology-note/java/springboot系列/数据库/2.springboot整合redis缓存.md
2019-03-11 14:12:37 +08:00

244 lines
7.2 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: '2019-02-22-14-59'
date: '2019/02/22 14:59:00'
title: 'springboot整合redis'
tag: ['java', 'spring-boot', 'redis', 'nosql', '缓存']
categories:
- 'java'
- 'spring boot学习'
---
![薄暮传说](https://raw.githubusercontent.com/FleyX/files/master/blogImg/20190311141056.png)
**本篇原创发布于:**[springboot整合redis](http://www.tapme.top/blog/detail/2019-02-22-14-59)
**项目源码:**[github](https://github.com/FleyX/demo-project/tree/master/1.SSO%E5%8D%95%E7%82%B9%E7%99%BB%E5%BD%95/sso)
  redis 作为一个高性能的内存数据库,如果不会用就太落伍了,之前在 node.js 中用过 redis本篇记录如何将 redis 集成到 spring boot 中。提供 redis 操作类,和注解使用 redis 两种方式。主要内容如下:
- docker 安装 redis
- springboot 集成 redis
- 编写 redis 操作类
- 通过注解使用 redis
# 安装 redis
  通过 docker 安装docker compose 编排文件如下:
```yml
# docker-compose.yml
version: '2'
services:
redis:
container_name: redis
image: redis:3.2.10
ports:
- '6379:6379'
```
  然后在`docker-compose.yml`所在目录使用`docker-compose up -d`命令,启动 redis。
<!-- readmore -->
# 集成 springboot
&emsp;&emsp;说明springboot 版本为 2.1.3
## 添加 maven 依赖
&emsp;&emsp;只需添加`spring-boot-starter-data-redis`依赖即可
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
```
## 编写 springboot 配置文件
&emsp;&emsp;配置文件如下:
```yaml
server:
port: 8081
servlet:
context-path: /sso
spring:
application:
name: SSO
cache:
type: redis
redis:
database: 0
host: 192.168.226.5
port: 6379
# 有密码填密码,没有密码不填
password:
# 连接超时时间ms)
timeout: 1000ms
# 高版本springboot中使用jedis或者lettuce
jedis:
pool:
# 连接池最大连接数(负值表示无限制)
max-active: 8
# 连接池最大阻塞等待时间(负值无限制)
max-wait: 5000ms
# 最大空闲链接数
max-idle: 8
# 最小空闲链接数
min-idle: 0
```
## 编写配置类
&emsp;&emsp;配置类代码如下:
```java
@EnableCaching//开启缓存
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
/**
* 设置缓存管理器,这里可以配置默认过期时间等
*
* @param connectionFactory 连接池
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(60));
//注意请勿使用先new 配置对象然后在调用entryTtl方法的方式来操作
//会导致配置不生效,原因是调用.entryTtl方法会返回一个新的配置对象而不是在原来的配置对象上修改
RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
RedisCacheManager manager = new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
return manager;
}
@SuppressWarnings("all")
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisSerializer stringSerializer = new StringRedisSerializer();
template.setKeySerializer(stringSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashKeySerializer(stringSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
```
## 使用方法
&emsp;&emsp;有两种方法来进行缓存操作,一种是在方法上添加缓存注解实现各种操作,一种是手动控制。个人比较喜欢手动控制,觉得这样都在自己的掌控中。
### 通过注解使用
&emsp;&emsp;主要有以下 5 个注解:
- `@CacheConfig`: 类级别缓存,设置缓存 key 前缀之类的
- `@Cacheable`: 触发缓存入口
- `@CacheEvict`: 触发移除缓存
- `@CachePut`: 更新缓存
- `@Caching`: 组合缓存
#### @CacheConfig
&emsp;&emsp;该注解可以将缓存分类,它是类级别注解,主要用于给某个类的缓存全局配置,例子如下:
```java
@CacheConfig(cacheNames = "redis_test")
@Service
public class RedisService {
//....
}
```
上面 CacheConfig 会给类下通过注解生成的 key 加上 redis_test 的前缀。
#### @Cacheable
&emsp;&emsp;方法级别注解,根据 key 查询缓存:
- 如果 key 不存在,将方法返回值缓存到 redis 中
- 如果 key 存在,直接从缓存中取值
例子如下:
```java
/**
* 缓存时间,首次查询后会缓存结果,key中的值可使用表达式计算.
* 如不提供key将使用默认key构造方法生成一个key
* @return long
*/
@Cacheable(key = "'currentTime'")
public long getTime() {
return System.currentTimeMillis();
}
```
多次调用此段代码会发现每次返回的值都是一样的。
#### CachePut
&emsp;&emsp;用于更新缓存,每次调用都会想 db 请求,缓存数据
- 如果 key 存在,更新内容
- 如果 key 不存在,插入内容
代码如下:
```java
/**
* 一般用于更新查插入操作每次都会请求db
*/
@CachePut(key = "'currentTime'+#id")
public long updateTime(String id) {
return System.currentTimeMillis();
}
```
每次调用此方法都会根据 key 刷新 redis 中的缓存数据。
#### @CacheEvict
&emsp;&emsp;根据 key 删除缓存中的数据。allEntries=true 表示删除缓存中所有数据。
代码如下:
```java
@CacheEvict(key = "'currentTime'+#id",allEntries=false)
public void deleteTime(String id) {
}
```
#### @Caching
&emsp;&emsp;本注解可将其他注解组合起来使用。比如下面的例子:
```java
//value属性为key指定前缀
@Caching(put = {@CachePut(value = "user", key = "'name_'+#user.name"),
@CachePut(value = "user", key = "'pass_'+#user.password")})
public User testCaching(User user) {
return user;
}
```
上面的代码执行后将在redis中插入两条记录。使用`keys *`将看到如下结果:
![结果](https://raw.githubusercontent.com/FleyX/files/master/blogImg/20190311140300.png)
### 手动控制
&emsp;&emsp;手动控制就相当于mybatis的手写sql语句需要调用`redisTemplate`中的各种方法来进行缓存查询,缓存更新,缓存删除等操作。
&emsp;&emsp;使用方法参见util/RedisUtil中的方法。`redisTemplate`基本可以实现所有的redis操作。