Spring Boot 整合——Redis实现简单的发布订阅以及配置序列化方式

设置序列化方式

为key和value配置特殊的序列化工具

下面的内容,使得key使用了StringRedisSerializer序列化工具。
使用value 使用了jackson2JsonRedisSerializer的序列化工具

@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // json序列化
        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);

        template.setConnectionFactory(factory);
        // key序列化方式
        template.setKeySerializer(new StringRedisSerializer());
        // value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // value hasHmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory 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);

        // 配置序列化(解决乱码的问题),过期时间30秒
        RedisCacheConfiguration config = 
                RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(30))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();

        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}

要想检测配置是否成功,可以使用下面的测试内容

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = RedisApplication.class)
@Slf4j
public class TestSerializer {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 启动RedisConfig配置的时候可以此测试可以通过,否则无法通过
     */
    @Test
    public void setUserByJackson2JsonRedisSerializer() {
        User user = new User();
        user.setAge(10);
        user.setName("user");
        user.setId(1L);
        redisTemplate.opsForValue().set("test",user);
        Object o = redisTemplate.opsForValue().get("test");
        Assert.assertTrue(o instanceof User);
        Assert.assertEquals("user",((User)o).getName());
    }

    /**
     * 启动RedisConfig配置的时候可以此测试可以无法通过,否则通过
     */
    @Test
    public void setIntKey() {
        redisTemplate.opsForValue().set(10L,"10");
        Object o = redisTemplate.opsForValue().get(10L);
        Assert.assertEquals("10",o);
    }

}

因为我们设置key使用了字符串序列化方式所以setIntKey使用long类型作为key会抛出异常,而setUserByJackson2JsonRedisSerializer则会通过。

setIntKey抛出的异常

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String

	at org.springframework.data.redis.serializer.StringRedisSerializer.serialize(StringRedisSerializer.java:35)
	at org.springframework.data.redis.core.AbstractOperations.rawKey(AbstractOperations.java:111)
	at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:59)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224)
	at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
	at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:95)
	at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:198)
    ......

假如我们取消掉配置的内容,因为setUserByJackson2JsonRedisSerializer尝试保存对象而不是字符串,则会抛出下面的异常。

org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [dai.samples.core.entitiy.User]

	at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:96)
	at org.springframework.data.redis.core.AbstractOperations.rawValue(AbstractOperations.java:126)
	at org.springframework.data.redis.core.DefaultValueOperations.set(DefaultValueOperations.java:197)
	at dai.samples.redis.base.service.impl.TestSerializer.setUserByJackson2JsonRedisSerializer(TestSerializer.java:35)
	......

使用redis实现消息队列

根据之前的API文档我们可以发现redisTemplate的convertAndSend方法,这个方法的作用
就是向指定通道发送消息,使用这个方法我们可以实现消息队列的操作

消息发送者

首先我们设置一个通道的名称

    /**
     * 通道名称
     */
    public static String CHANNEL = "dai.channel";

然后我们创建一个消息发送者

@Component
public class PubSend {

    @Autowired
    private StringRedisTemplate redisTemplate;


    /**
     * 发布消息到通道
     *
     * @param message
     */
    public void sendTopicMessage(String message) {
        redisTemplate.convertAndSend(RedisListenerConfig.CHANNEL,
                message);
    }
    
}

这样我们可以使用sendTopicMessage将消息发送至dai.channel通道中

消息监听者

要监听通道的消息,我们需要一个实现了org.springframework.data.redis.connection.MessageListener
的方法。然后我们可以在onMessage中处理接收到的消息。

@Slf4j
@Component
public class MyRedisMessageListener implements MessageListener {


    @Autowired
    private RedisTemplate <String, String> redisTemplate;
    /**
     * 接收消息的处理
     * Callback for processing received objects through Redis.
     *  @param message message must not be {@literal null}.
     * @param pattern pattern matching the channel (if specified) - can be {@literal null}.
     */
    @Override 
    public void onMessage(Message message, byte[] pattern) {
        byte[] body = message.getBody();
        byte[] channel = message.getChannel();
        String msgContent = 
                (String) redisTemplate
                        .getValueSerializer()
                        .deserialize(body);
        String topic = 
                redisTemplate
                        .getStringSerializer()
                        .deserialize(channel);
        // 设置输出内容
        log.info("redis--topic:" + topic + "  body:" + msgContent);
    }
}

配置监听

现在我们有了消息监听的类,现在只要我们将此监听器和通道进行绑定即可。这个时候需要使用
org.springframework.data.redis.listener.RedisMessageListenerContainer监听容器

@Configuration
public class RedisListenerConfig {
    /**
     * 通道名称
     */
    public static String CHANNEL = "dai.channel";

    @Bean 
    RedisMessageListenerContainer container(
            RedisConnectionFactory connectionFactory,
            MyRedisMessageListener listener) {
        // 新建监听对象
        RedisMessageListenerContainer container = 
                new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        // 订阅了一个通道
        container.addMessageListener(listener, new PatternTopic(CHANNEL));
        // 这个container 可以添加多个 messageListener
        return container;
    }
}

测试接口

现在我们配置一个测试的接口,进行消息请求的测试

@RestController
@RequestMapping("pub")
public class PubController {
    
    @Autowired
    private PubSend send;

    /**
     * 测试消息发送
     * @param message
     * @return
     */
    @RequestMapping(value = "send/{message}",method = RequestMethod.GET)
    public String send(@PathVariable("message") String message) {
        send.sendTopicMessage(message);
        return message;
    }
}

现在我们访问http://localhost:8000/pub/send//testMessage地址

在这里插入图片描述

现在我们查看控制台可以看到,通道的名称和消息内容已经成功输出

2019-08-07 21:24:19.060  INFO 19468 --- [    container-4] d.s.r.p.listener.MyRedisMessageListener  : redis--topic:dai.channel  body:testMessage

本篇文章涉及的源码下载地址:https://gitee.com/daifyutils/springboot-samples

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 好的,关于SpringBoot整合Redis配置的问题,我可以为您提供以下信息: 1. 首先需要在pom.xml文件中添加redis的依赖,如下所示: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 在application.properties或者application.yml配置文件中配置Redis相关的参数,例如: ``` # Redis服务器地址 spring.redis.host=127.0.0.1 # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(如果没有设置密码则为空) spring.redis.password= # Redis数据库索引(默认为0) spring.redis.database=0 # 连接超时时间(毫秒) spring.redis.timeout=10000 ``` 3. 在SpringBoot中使用Redis时,可以使用SpringRedisTemplate类进行操作,例如: ``` @Autowired private RedisTemplate<String, String> redisTemplate; // 存储数据到RedisredisTemplate.opsForValue().set("key", "value"); // 从Redis中获取数据 String value = redisTemplate.opsForValue().get("key"); ``` 以上是关于SpringBoot整合Redis配置的一些基本信息,希望能对您有所帮助。 ### 回答2: Spring Boot整合Redis配置主要包括以下步骤: 1. 在pom.xml文件中添加RedisSpring Boot Redis依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> ``` 2. 在application.properties或application.yml配置文件中配置Redis连接信息: ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= ``` 3. 创建Redis配置类,用于配置RedisTemplate和连接工厂: ```java @Configuration public class RedisConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.password}") private String password; @Bean public JedisConnectionFactory jedisConnectionFactory() { RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(); configuration.setHostName(host); configuration.setPort(port); configuration.setPassword(RedisPassword.of(password)); return new JedisConnectionFactory(configuration); } @Bean public RedisTemplate<String, Object> redisTemplate() { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(jedisConnectionFactory()); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } } ``` 4. 在需要使用Redis的类中通过@Autowired注入RedisTemplate,并使用相应的方法进行操作,例如: ```java @Autowired private RedisTemplate<String, Object> redisTemplate; public void setObject(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object getObject(String key) { return redisTemplate.opsForValue().get(key); } ``` 通过以上步骤,就完成了Spring Boot整合Redis配置。可以通过注入RedisTemplate来使用Redis相关的方法,如set、get等。 ### 回答3: Spring Boot整合Redis配置主要包括以下几个步骤: 1. 引入依赖:在pom.xml文件中添加Spring Boot提供的redis依赖。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis连接信息:在application.properties或application.yml文件中配置Redis的连接信息,包括主机名、端口号、密码等。 ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= ``` 3. 配置RedisTemplate:通过配置RedisTemplate来操作Redis,可以配置连接工厂、序列化方式等。 ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); // 设置Key的序列化方式 template.setKeySerializer(new StringRedisSerializer()); // 设置Value的序列化方式 template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } } ``` 4. 使用RedisTemplate操作Redis:在代码中通过@Autowired注入RedisTemplate,可以直接调用其方法来操作Redis。 ```java @Autowired private RedisTemplate<String, Object> redisTemplate; public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } ``` 通过以上步骤,我们就可以在Spring Boot中成功地整合配置Redis,然后通过RedisTemplate来进行相关的操作,如设置值、获取值等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值