Home SpringBoot接入Redis
Post
Cancel

SpringBoot接入Redis

配置

依赖

1
2
3
4
5
6
7
8
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
1
2
3
4
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-redis")
    implementation("org.apache.commons:commons-pool2")
}

application.yml配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server:
  port: 8082
  servlet:
    context-path: /demo
spring:
  redis:
    # 远程的地址,如果为本地可以不写
    host: xx.xx.xx.xx
    port: 6379
    # 远程密码,可以不写
    password: xxxx
    # 连接超时时间
    timeout: 10000ms
    database: 0
    lettuce:
      pool:
        # 连接池最大连接数 ,默认8,写负数表示没有限制
        max-active: 20
        # 连接池最大空闲连接,默认8
        max-idle: 5
        # 连接池最大阻塞等待时间
        max-wait: 5000ms
        # 连接池中的最小空闲连接,默认0
        min-idle: 20

基础命令

链接本地redis服务

1
redis-cli

如果有设置密码,则使用来登录

1
redis-cli -a <password>
代码获取操作对象

直接依赖注入

1
2
@Autowired
private lateinit var redisTemplate: StringRedisTemplate

存储字符串

类似map,根据key存储字符串,也提供对于数字的增加或减少操作,可以用于统计热度等需要频繁更新的数据,减少数据库访问

客户端命令
1
2
3
4
5
6
7
8
9
10
11
# 设置指定 key 的值。
SET key value

# 根据key获取值,如果为空返回(nil)
GET key

# 给 key 设置新 value ,并返回旧值
GETSET key value

# 给key的value加一,必须要是整数
INCR key
代码访问
1
2
3
4
5
6
// 获取字符串操作对象
val operations = redisTemplate.opsForValue()
operations.get("key")
operations.set("key","value")
// 给定加一,没有的默认为0
operations.increment("key", 1L)

List

Redis列表类似与双向队列,可以从左边或者右边插入元素,会保持元素插入顺序。

客户端命令
1
2
3
4
5
6
7
8
9
10
11
# 将值添加到列表头部
LPUSH key value

# 获取指定列表范围元素
LRANGE key start stop

# 移除列表元素
LREM key count value

# 移出并获取列表的第一个元素
LPOP key
代码访问
1
2
3
4
5
val list = redisTemplate.opsForList()
list.leftPush("list", "value0")
list.leftPop("list")
// 是左index
list.index("list", 1)

SET

和Java的set类似,使用Hash表实现,不能有重复元素,也是无序的。

客户端命令
1
2
3
4
5
6
7
8
9
10
11
# 添加元素
SADD key member

# 获取size
SCARD key

# 返回所有元素
SMEMBERS key

# 获取一个元素
SPOP key
代码访问
1
2
3
4
val set = redisTemplate.opsForSet()
set.add("set", "value")
val member: Boolean? = set.isMember("set","value")
val members: Set<String>? = set.members("set")

ZSET

带有顺序的set,关联一个score来进行排序,score可以重复,元素不可以重复

客户端命令
1
2
3
4
5
# 向有序集合添加一个元素,或更新分数
ZADD key score1 member1

# 获取有序集合的成员数
ZCARD key
代码访问
1
2
3
4
5
val set = redisTemplate.opsForZSet()
set.add("set", "value1", 1.0)
set.add("set", "value2", 1.0)
set.popMin("set")
set.popMax("set")

Hash

1
2
# 获取存储在哈希表中指定字段的值。
HGET key field
1
2
3
val map = redisTemplate.opsForHash<String, String>()
map.put("map", "key", "value")
map.get("map","key")

Cache

启动类添加注解@EnableCaching

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableCaching
public class SpringBootStudyApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootStudyApplication.class, args);
    }

}

配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.jfp.study;

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.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class RedisConfig {

    @Bean
    RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        redisCacheConfiguration.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));

        Map<String, RedisCacheConfiguration> redisExpireConfig = new HashMap<>();
        //这里设置了一个一分钟的超时配置,如果需要增加更多超时配置参考这个新增即可
        redisExpireConfig.put("1min", RedisCacheConfiguration.defaultCacheConfig()
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .entryTtl(Duration.ofMinutes(1)).disableCachingNullValues());

        RedisCacheManager redisCacheManager = RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheConfiguration)
                .withInitialCacheConfigurations(redisExpireConfig)
                .transactionAware()
                .build();
        return redisCacheManager;
    }
}

实体类

此处如果直接使用kotlin的data class,需要结合@JsonTypeInfo

1
2
3
4
5
6
7
8
public class User {

    private String name;
    private String uid;
    private String email;
    
    //get && set ....
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@RequestMapping(value = "/user")
public class UserController {

    @GetMapping(value = "/info")
    @Cacheable(value = "user", key = "#uid")
    public User getUser(@RequestParam(value = "uid") String uid) {
        System.out.println("getUser====>" + uid);
        User user = new User();
        user.setUid(uid);
        user.setEmail(uid + "@definesys.com");
        user.setName(uid + ":" + System.currentTimeMillis());
        return user;
    }
}

校验

1
2
3
4
## 输入
curl 192.168.0.108:8082/demo/user/info?uid=jiangker01
## 输出
{"name":"jiangker01: 1647752522128","uid":"jiangker01","email":"jiangker01@definesys.com"}

缓存过期

1
2
3
4
5
6
7
8
9
10
11
//这里设置了一个一分钟的超时配置,如果需要增加更多超时配置参考这个新增即可
redisExpireConfig.put("1min", RedisCacheConfiguration.defaultCacheConfig()
        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
        .entryTtl(Duration.ofMinutes(1)).disableCachingNullValues());

@GetMapping(value = "/info")
@Cacheable(value = "1min", key = "#uid")
public User getUser(@RequestParam(value = "uid") String uid) {
    //...
}

则存入的数据会在一分钟之后过期。

缓存相关注解

除了Cacheable还有其他跟缓存相关的注解

  • CachePut

    CachePut可以将数据放入缓存,一般insert操作和update操作可以使用该注解,如果指定的key数据存在就更新数据

  • CacheEvict

    CacheEvict可以删除缓存数据,一般delete操作的接口可以使用该注解

  • Caching

    Caching是三个的集合,定义如下

1
2
3
4
5
public @interface Caching {
    Cacheable[] cacheable() default {};
    CachePut[] put() default {};
    CacheEvict[] evict() default {};
}

完整案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@RestController
@RequestMapping("user")
public class RedisController {

    @Autowired
    private UserMapper userMapper;

    @PostMapping("/add")
    @CachePut(value = "neverExpire", key = "#user.uid")
    public User add(@RequestBody User user) {
        userMapper.insert(user);
        return user;
    }

    @PostMapping("/update")
    @CachePut(value = "neverExpire", key = "#user.uid")
    public User update(@RequestBody User user) {
        return user;
    }

    @GetMapping("/delete")
    @CacheEvict(value = "neverExpire", key = "#uid")
    public String delete(@RequestParam(value = "uid") String uid) {
        return uid;
    }

    @GetMapping("/detail")
    @Cacheable(value = "neverExpire", key = "#result")
    public User deteail(@RequestParam(value = "uid") String uid) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uid", uid);
        return userMapper.selectOne(queryWrapper);
    }
}

参考

Spring boot 集成Redis

This post is licensed under CC BY 4.0 by the author.