Spring Boot入门系列之:九、Spring Boot整合Redis

本文详细介绍如何在SpringBoot环境中配置并使用Redis,包括项目搭建、依赖配置、连接池设置及缓存管理。涵盖字符串、散列、列表、集合、有序集合等数据结构操作,以及JSON序列化和自定义缓存配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring Boot Redis

开发环境

开发工具: Intellij IDEA 2018.2.6

springboot: 2.0.7.RELEASE

jdk: 1.8.0_192

maven: 3.6.0

redis: 4.0.12

redis 简介

什么是 redis ?

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

搭建项目

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">

    <groupId>com.andy</groupId>
    <artifactId>spring-boot-redis</artifactId>
    <version>1.0.7.RELEASE</version>
    <modelVersion>4.0.0</modelVersion>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>io.spring.platform</groupId>
                <artifactId>platform-bom</artifactId>
                <version>Cairo-SR6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.0.6.RELEASE</version>
                <configuration>
                    <!--<mainClass>${start-class}</mainClass>-->
                    <layout>ZIP</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

  • application.yml
server:
  port: 8081
  servlet:
    context-path: /

spring:
  application:
    name: spring-redis
  redis:
    # 数据库索引
    database: 3
    # 连接超时时间
    timeout: 10000ms
    # ip地址
    host: 127.0.0.1
    # 端口
    port: 6379
    # 密码
    # password:
    jedis:
      pool:
        # 最大连接数
        max-active: 8
        # 最大阻塞等待时间(负数表示没限制)
        max-wait: -1ms
        # 最大空闲
        max-idle: 8
        # 最小空闲
        min-idle: 0
  • 启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

/**
 * @author Leone
 * @since 2018-05-11
 **/
@EnableCaching
@SpringBootApplication
public class RedisApplication {
    public static void main(String[] args) {
        SpringApplication.run(RedisApplication.class, args);
    }
}

  • RedisConfig.java

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
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.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

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

/**
 * <p> redis配置
 *
 * @author Leone
 * @since 2018-07-19
 **/
@Configuration
public class RedisConfig extends CachingConfigurerSupport {


    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        // 设置缓存的默认过期时间,也是使用Duration设置
        config = config.entryTtl(Duration.ofMinutes(1))
                // 不缓存空值
                .disableCachingNullValues();

        // 设置一个初始化的缓存空间set集合
        Set<String> cacheNames = new HashSet<>();
        cacheNames.add("my-redis-cache1");
        cacheNames.add("my-redis-cache2");

        // 对每个缓存空间应用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("my-redis-cache1", config);
        configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120)));

        // 使用自定义的缓存配置初始化一个cacheManager
        return RedisCacheManager.builder(factory)
                // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
                .initialCacheNames(cacheNames)
                .withInitialCacheConfigurations(configMap)
                .build();
    }

    /**
     * 设置 redis 入库 各种类型 k v 序列化
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//        RedisSerializer<String> stringSerializer = new StringRedisSerializer();

        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();

        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(jackson2JsonRedisSerializer);
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

}
  • User.java
import java.io.Serializable;
import java.util.Date;

/**
 * <p>
 *
 * @author Leone
 * @since 2018-03-02
 **/
public class User implements Serializable {

    private Long userId;

    private String account;

    private String password;

    private String description;

    private Integer age;

    private Date createTime;

    private boolean deleted;

    public User() {
    }

    public User(Long userId, String account, String password, String description, Integer age, Date createTime, Boolean deleted) {
        this.userId = userId;
        this.account = account;
        this.password = password;
        this.description = description;
        this.age = age;
        this.createTime = createTime;
        this.deleted = deleted;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public boolean isDeleted() {
        return deleted;
    }

    public void setDeleted(boolean deleted) {
        this.deleted = deleted;
    }
}

  • RedisPrefix.java
/**
 * redis 前缀生成器
 *
 * @author Leone
 * @since 2018-07-08
 **/
public class RedisPrefix {

    public static String userCatch(String uuid) {
        return "app.user:" + uuid;
    }

}
  • RedisController.java

import com.andy.redis.service.RedisCacheService;
import com.andy.redis.service.RedisService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author Leone
 * @since 2018-07-08
 **/
@RestController
@RequestMapping("/api/redis")
public class RedisController {

    @Resource
    private RedisService redisService;

    @Resource
    private RedisCacheService redisCacheService;

    @GetMapping("/list")
    public String list() {
        return "list: " + redisService.list() + " !";
    }

    @GetMapping("/value")
    public String value() {
        return "value: " + redisService.value() + " !";
    }

    @GetMapping("/set")
    public String set() {
        return "set " + redisService.set() + " !";
    }


    @GetMapping("/zSet")
    public String zSet() {
        return "zSet " + redisService.zSet() + " !";
    }

    @GetMapping("/hash")
    public String hash() {
        return "hash " + redisService.hash() + " !";
    }


    @GetMapping("/catch")
    public String userCatch() {
        return redisCacheService.userCatch();
    }

}

  • RedisService.java

import com.andy.redis.config.RedisPrefix;
import com.andy.redis.util.EntityFactory;
import com.andy.redis.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisZSetCommands;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *
 * @author Leone
 * @since 2018-08-11
 **/
@Slf4j
@Service
public class RedisService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 相当于队列操作
     *
     * @return
     */
    public long list() {
        log.info("list:{}", 1);
        for (int i = 0; i < 10; i++) {
            String key = RedisPrefix.userCatch("list"), value = RandomUtil.getName();
            Long push = redisTemplate.opsForList().leftPush(key, value);
            log.info("leftPush key:[{}] -- value:[{}]", key, value);
        }

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < 9; i++) {
            Object result = redisTemplate.opsForList().rightPop(RedisPrefix.userCatch("list"));
            log.info("leftPop key:[{}] -- value:[{}]", i, result);
        }

        return 1;
    }

    /**
     * set 普通 字符串或对象 类型数据
     *
     * @return
     */
    public long value() {
        log.info("value:{}", 1);
        redisTemplate.opsForValue().set(RedisPrefix.userCatch(RandomUtil.getNum(6)), EntityFactory.getUser(), 120, TimeUnit.SECONDS);
        return 1;
    }


    /**
     * set 操作
     *
     * @return
     */
    public long set() {
        log.info("set:{}", 1);
        // set值
        Long add = redisTemplate.opsForSet().add("key1", "dd", "bb", "ee", "aa");

        // 获取值
        Set<Object> resultSet = redisTemplate.opsForSet().members("key1");

        // 获取变量中值的长度
        Long size = redisTemplate.opsForSet().size("key1");

        // 随机获取变量中的元素
        Object randomVal = redisTemplate.opsForSet().randomMember("key1");

        // 随机获取变量中指定个数的元素
        List<Object> randomValues = redisTemplate.opsForSet().randomMembers("key1", 3);

        //  检查给定的元素是否在变量中
        Boolean isMember = redisTemplate.opsForSet().isMember("key1", "ff");

        // 转移变量的元素值到目的变量
        //Boolean move = redisTemplate.opsForSet().move("key1", "aa", "ee");

        // 弹出变量中的元素
        //List<Object> key1 = redisTemplate.opsForSet().pop("key1", 1);

        // 批量移除变量中的元素。
        //Long remove = redisTemplate.opsForSet().remove("key1", "aa", "bb");

        // 匹配获取键值对,ScanOptions.NONE为获取全部键值对;ScanOptions.scanOptions().match("C").build()匹配获取键位map1的键值对,不能模糊匹配。
        /*Cursor<Object> cursor = redisTemplate.opsForSet().scan("setValue", ScanOptions.scanOptions().match("c").build());
        while (cursor.hasNext()){
            Object object = cursor.next();
            System.out.println("通过scan(K key, ScanOptions options)方法获取匹配的值:" + object);
        }*/

        log.info("size: {} randomVal: {} randomValues: {} resultSet: {} isMember: {}", size, randomVal, randomValues, resultSet, isMember);
        return 1;
    }


    public long zSet() {
        log.info("zSet:{}", 1);
        redisTemplate.opsForZSet().add(RedisPrefix.userCatch(RandomUtil.getNum(6)), EntityFactory.getUser(), 3);

        redisTemplate.opsForZSet().add("zSetValue", "A", 1);
        redisTemplate.opsForZSet().add("zSetValue", "B", 3);
        redisTemplate.opsForZSet().add("zSetValue", "C", 2);
        redisTemplate.opsForZSet().add("zSetValue", "D", 5);

        // 获取指定区间的元素
        Set zSetValue = redisTemplate.opsForZSet().range("zSetValue", 0, -1);
        log.info("range: {}", zSetValue);


        // 用于获取满足非score的排序取值。这个排序只有在有相同分数的情况下才能使用,如果有不同的分数则返回值不确定。
        RedisZSetCommands.Range range = new RedisZSetCommands.Range();
        // range.gt("A");
        range.lt("D");
        zSetValue = redisTemplate.opsForZSet().rangeByLex("zSetValue", range);
        log.info("rangeByLex: {}", zSetValue);

        // 通过TypedTuple方式新增数据
        ZSetOperations.TypedTuple<Object> typedTuple1 = new DefaultTypedTuple<>("E", 6.0);
        ZSetOperations.TypedTuple<Object> typedTuple2 = new DefaultTypedTuple<>("F", 7.0);
        ZSetOperations.TypedTuple<Object> typedTuple3 = new DefaultTypedTuple<>("G", 5.0);
        Set<ZSetOperations.TypedTuple<Object>> typedTupleSet = new HashSet<>();

        typedTupleSet.add(typedTuple1);
        typedTupleSet.add(typedTuple2);
        typedTupleSet.add(typedTuple3);
        redisTemplate.opsForZSet().add("typedTupleSet", typedTupleSet);
        zSetValue = redisTemplate.opsForZSet().range("typedTupleSet", 0, -1);
        log.info("添加元素:{}", zSetValue);

        long count = redisTemplate.opsForZSet().count("zSetValue", 1, 5);
        log.info("获取区间值的个数:{}", count);

        return 1;
    }

    /**
     * @return
     */
    public long hash() {
        log.info("hash:{}", 1);
        // put() 添加
        redisTemplate.opsForHash().put("he1", "key1", EntityFactory.getUser());
        redisTemplate.opsForHash().put("he1", "key2", EntityFactory.getUser());
        redisTemplate.opsForHash().put("he1", "key3", EntityFactory.getUser());
        Map<Object, Object> entries = redisTemplate.opsForHash().entries("he1");
        log.info("put:{}", entries);

        // putAll() 批量添加
        Map<String, Object> param = new HashMap<>();
        param.put("key1", EntityFactory.getUser());
        param.put("key2", EntityFactory.getUser());
        param.put("key3", EntityFactory.getUser());
        redisTemplate.opsForHash().putAll("he2", param);
        log.info("putAll:{}", redisTemplate.opsForHash().entries("he2"));

        // delete() 删除指定key
        redisTemplate.opsForHash().delete("he3", "key1");
        log.info("delete:{}", redisTemplate.opsForHash().entries("he3"));

        // hasKey() 判断某个key是否存在
        log.info("hasKey:{}", redisTemplate.opsForHash().hasKey("he2", "key2"));

        // get() 获取值
        log.info("get:{}", redisTemplate.opsForHash().get("he2", "key1"));

        // multiGet() 批量获取
        log.info("multiGet:{}", redisTemplate.opsForHash().multiGet("he2", Arrays.asList("key1", "key2")));

        // 获取所有key
        log.info("keys:{}", redisTemplate.opsForHash().keys("he2"));

        // 获取所有key size
        log.info("size:{}", redisTemplate.opsForHash().size("he2"));

        // 获取所有key values
        log.info("values:{}", redisTemplate.opsForHash().values("he2"));

        Cursor<Map.Entry<Object, Object>> scan = redisTemplate.opsForHash().scan("he2", ScanOptions.NONE);
        while (scan.hasNext()) {
            Map.Entry<Object, Object> entry = scan.next();
            log.info("key:{} -- value:{}", entry.getKey(), entry.getValue());
        }

        return 1;
    }
}

传送门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值