SpringBoot集成Redis之RedisTemplate

一、 单机版

1.建module

2.改pom

 <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- 导入Spring Boot的依赖管理 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.6.10</version> <!-- 替换为合适的Spring Boot版本 -->
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 其他需要的依赖管理也可以放在这里 -->
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- guava Google 开源的 Guava 中自带的布隆过滤器 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>
        <!-- SpringBoot通用依赖模块 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>4.3.1</version>
        </dependency>
        <!-- lettuce -->
        <dependency>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                    <version>6.1.10.RELEASE</version>
                </dependency>
        <!-- SpringBoot与Redis整合依赖 -->
        <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>
        <!-- swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- Mysql数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!-- SpringBoot集成druid连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
        <!-- mybatis和springboot整合 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!-- hutool -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.2.3</version>
        </dependency>
        <!-- persistence -->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0.2</version>
        </dependency>
        <!-- 通用Mapper -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>4.1.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <!-- 通用基础配置junit/devtools/test/log4j/lombok/ -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <optional>true</optional>
        </dependency>
    </dependencies>
 

3.写properties

server.port=7777
spring.application.name=SSM-demo1
logging.level.root=info
logging.level.com.yyt=info
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} %msg%n
logging.file.name=D:/mylogs2024/redis7_study.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n
​
#==================================swagger==============================================
spring.swagger2.enabled=true
strategy=ant_path_matcher
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
#================================redis单机版================================
spring.redis.database=0
spring.redis.host=192.168.80.130
spring.redis.port=6379
spring.redis.password=123456
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
#================================mysql=================================
spring.datasource.url=jdbc:mysql://localhost:3306/yangyutong
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

4.主启动

redis-server /myredis/redis7.conf #开启redis服务 必须加载配置文件
​
redis-cli -a 123456 -p 6379  #开启客户端

5.业务类

(1)编写swaggerConfig

@EnableSwagger2
public class Swagger2Config {
    @Value("${spring.swagger2.enabled}")
    private Boolean enabled;
​
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                //为当前包路径,控制器类包
                .apis(RequestHandlerSelectors.basePackage("com.yyt"))
                .paths(PathSelectors.any())
                .build();
    }
​
    //构建 api文档的详细信息函数
    private ApiInfo apiInfo() {
        Instant now = Instant.now(); // 获取当前时间
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 定义时间格式器
        String formattedTime = now.atZone(java.time.ZoneId.systemDefault()).format(formatter);// 格式化时间
        return new ApiInfoBuilder()
                //页面标题
                .title("springboot利用swagger构建api文"+"\t"+formattedTime)
                //创建人
                .contact(new Contact("yyt", "https://www.baidu.com",
                        "hahaha8@qq.com"))
                //版本号
                .version("1.0")
                //描述
                .description("spring+redis整合")
                .build();
    }
}

(2) 编写controller类 OrderController

@RestController
@Slf4j
@Api(tags = "订单接口")
public class OrderController {
    @Resource
    private OrderService orderService;
​
    @ApiOperation("新增订单")
    @RequestMapping(value = "/order/add",method = RequestMethod.POST) //了解一下常见四种请求方式的区别
    public void addOrder(){
        orderService.addOrder();
    }
​
    @ApiOperation("根据订单编号查询订单")
    @RequestMapping(value = "/order/{keyId}",method = RequestMethod.GET)
    public void getOrderBykeyId(@PathVariable Integer keyId){
​
        orderService.getOrderById(keyId);    }
}

(3)编写Service类 OrderService

@Service
@Slf4j
public class OrderService {
    @Resource
    private RedisTemplate redisTemplate;
    public static final String ORDER_KEY="ord";
    public void addOrder() {
        //ThreadLocalRandom.current().nextInt(10000)生成1-10000的随机数作为keyId
        int keyId = ThreadLocalRandom.current().nextInt(10000) + 1;
        //生成一个随机的UUID作为value订单号
        String serialNo = UUID.randomUUID().toString();
        //将keyId和serialNo拼接成key
        String key = ORDER_KEY + keyId;
        //value为订单信息
        String value = "京东订单"+serialNo;
        //将key和value存入redis中
        redisTemplate.opsForValue().set(key, value);
        //输出日志信息
        log.info("****keyId:{}", key);
        log.info("****value:{}",value);
​
    }
    public String getOrderById(Integer keyId){
        //通过传入随机生成的keyId来拼出订单信息的key
        String key = ORDER_KEY + keyId;
        //通过key来获取订单信息的value
        String value = (String) redisTemplate.opsForValue().get(key);
        return value;
    }
}
​

(4)启动类配置 RedisStudy7777

//启动微服务
@EnableSwagger2
@SpringBootApplication
public class Redis7Study7777 {
    public static void main(String[] args) {
        SpringApplication.run(Redis7Study7777.class, args);
    }
}

6.测试

运行启动类--->访问http://localhost:7777/swagger-ui.html,端口改为自己设置的server.port

 访问http://localhost:端口号/swagger-ui.html,点击try it out

出现excute后点击excute

返回200表示请求顺利给到后端了

后端控制台查看订单信息

看看是否写入redis

序列化问题
写是写入了但是咋跟我们想要看到的不一样呢?
spring写入数据到redis原理:
Key和Value都是通过Spring提供的序列化到数据库的。

RedisTemplate默认使用JdkSerializeationalRedisSerializer不用Redis的序列化接口

StringRedisTemplate默认使用StringRedisSerializer,StringRedisTemplate在生成构造方法时,默认调用了序列化接口。

解法1

使用StringRedisTemplate对象,即redisTemplate---->StringRedisTemplate

继续新增订单,再次查询redis

产生问题

首先后端显示正常,然后在swagger里查,也能返回正确的value,只有redis服务器中显示不正常。

解决:登录redis客户端时末尾追加--raw,就可以解决乱码问题。

解法2

RedisConfig类中自构造redisTemplate对象,让其实现序列化接口

@Configuration
public class RedisConfig
{
    /**
     * redis序列化的工具配置类,下面这个请一定开启配置
     * 127.0.0.1:6379> keys *
     * 1) "ord:102"  序列化过
     * 2) "\xac\xed\x00\x05t\x00\aord:102"   野生,没有序列化过
     * this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法
     * this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法
     * this.redisTemplate.opsForSet(); //提供了操作set的所有方法
     * this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法
     * this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法
     * @param lettuceConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
    {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();

        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
        //设置key序列化方式string
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }
}

再次新增订单后,到redis中查询

一切正常。

二、集群

1.修改properties

注释掉单机版的配置,新增

spring.redis.password=123456
spring.redis.cluster.nodes=192.168.80.130:6379,192.168.80.130:6380,192.168.80.131:6381,192.168.80.131:6382,192.168.80.132:6383,192.168.80.132:6384
#最大重定向次数
spring.redis.cluster.max-redirects=3
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0

2.启动redis集群

这里只启动一个,其他同理

redis-server /myredis/cluster/redisCluster6379.conf #加载配置文件
redis-cli -a 20030129 -p 6379 -c --raw  #启动一个客户端,便于查看集群信息
#--raw 解决redis客户端乱码显示
#-c 可以使当前主机get到set进其他主机的的key的值

3.微服务类启动

和单机版同理

4.效果

经典错误

连接好好的,突然有一台redis宕机了,虽然从机很快上位,但微服务对redis的连接被拒绝了

导致原因

springboot在2.x-2.3.0版本之前,Redis默认使用的连接池采用lettuce,当集群节点发生变化,lettuce默认不会刷新拓扑节点。

解决方案
(1) pom文件中lettuce------->jedis(不好)

新瓶装旧酒

(2) 重写连接工厂实例(极不推荐)
@Bean
public DefaultClientResources lettuceClientResources() {
    return DefaultClientResources.create();
}

@Bean
public LettuceConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties, ClientResources clientResources) {

    ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
            .enablePeriodicRefresh(Duration.ofSeconds(30)) //按照周期刷新拓扑
            .enableAllAdaptiveRefreshTriggers() //根据事件刷新拓扑
            .build();

    ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
            //redis命令超时时间,超时后才会使用新的拓扑信息重新建立连接
            .timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(10)))
            .topologyRefreshOptions(topologyRefreshOptions)
            .build();

    LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder()
            .clientResources(clientResources)
            .clientOptions(clusterClientOptions)
            .build();

    RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
    clusterConfig.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());
    clusterConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));

    LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(clusterConfig, clientConfiguration);

    return lettuceConnectionFactory;
}
(3) 刷新集群节点动态感应(推荐)

application.properties中新增

#允许动态刷新集群
spring.redis.lettuce.cluster.refresh.adaptive=true
#刷新间隔
spring.redis.lettuce.cluster.refresh.period=2000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值