Redis的消息

部分参考链接

原文

CountDownLatch

概述

目的

这节讲的是用Redis来实现消息的发布和订阅,这里会使用Spring Data Redis来完成。

这里会用到两个东西,StringRedisTemplateMessageListenerAdapter。分别用来发布String类型的消息和订阅接收这些消息。

你需要的准备的

  • 大概15min(实际用下来应该不够)
  • 喜欢的ide或者文本编辑器(我使用intellij)
  • Jdk1.8+
  • Gradle4+ 或者 Maven3.2+(这里用Maven)

如何通过Maven来完成

新建maven项目

创建pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2019.
~ lou
--> <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">
<modelVersion>4.0.0</modelVersion> <groupId>org.springframework</groupId>
<artifactId>gs-messaging-redis</artifactId>
<version>1.0-SNAPSHOT</version> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.5.2.RELEASE</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

Spring Boot Maven Plugin 有以下几个作用

  • 把项目打包成一个可执行的jar文件。
  • 搜索并标记public static void main()为可执行类。
  • 使用内置的依赖管理

需要一个Redis Server

这里还需要一个Redis Server,搭设过程就不演示了,假设已经搭好,server: localhost:6379, password:xxxxxx。

创建一个Redis 消息接收类

src/main/java/hello/Receiver.java

/*
* Copyright (c) 2019.
* lou
*/ package hello; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import java.util.concurrent.CountDownLatch; public class Receiver { private static final Logger logger = LoggerFactory.getLogger(Receiver.class); private CountDownLatch latch; @Autowired
public Receiver(CountDownLatch latch) {
this.latch = latch;
} public void receiveMessage(String message){
logger.info("接收到消息"+message);
latch.countDown();
} }

CountDownLatch用来阻塞当前进程,调用countDown方法一次减少1,到0释放。。CountDownLatch 无法重置,如有需要,使用CyclicBarrier

创建一个Redis配置类

Redis的配置应该是放在配置文件中的,所以需要创建一个redis配置类,来读取resource/application.properties中的配置并赋值给相应的connectionFactory。

先添加一下application.properties

spring.redis.password=xxxxx
spring.redis.port=6379
spring.redis.host=localhost

然后创建一个hello/RedisStandaloneConfigurationPropertySource.java

/*
* Copyright (c) 2019.
* lou
*/ package hello; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; //配置RedisConnectionFactory
@Configuration
@PropertySource(value = "application.properties",encoding = "utf-8")
public class RedisStandaloneConfigurationPropertySource {
private Logger logger = LoggerFactory.getLogger(RedisStandaloneConfigurationPropertySource.class);
@Value("${spring.redis.host}")
private String hostName;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password; @Override
public String toString() {
return "RedisStandaloneConfigurationPropertySource{" +
"hostName='" + hostName + '\'' +
", port=" + port +
", password='" + password + '\'' +
'}';
} @Bean
RedisConnectionFactory getRedisConnectionFactory() {
//日志记录一下
logger.info("redis的配置为:"+this.toString());
JedisConnectionFactory factory = new JedisConnectionFactory();
RedisStandaloneConfiguration configuration = factory.getStandaloneConfiguration();
configuration.setHostName(hostName);
configuration.setPort(port);
configuration.setPassword(password);
return factory;
}
}

这个类的功能就是读取配置文件,并且定义一个RedisConnectionFactory的Bean,后面会用到。

注册这个消息接收类并发送消息

Spring Data Redis提供了发送和接收消息的所有组件。重点需要配置以下几个东西

  • 一个Connection Factory(连接管理工厂)
  • 一个 Message Listener Container(消息接收容器)
  • 一个Redis Template

使用Redis Template来发送消息,然后把Receiver注册到Message Listener Container中。Connection Factory驱动Template和Container,让他们可以连接到redis server。

例子中使用Spring boot的RedisConnectionFactory,它是基于JedisJedisConnectionFactory的实例。Connection Factory会同时注入到container和template中。

src/main/java/hello/Application.java

/*
* Copyright (c) 2019.
* lou
*/ package hello; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter; import java.util.concurrent.CountDownLatch; @SpringBootApplication
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class); //Container 由RedisConnectionFactory 和MessageListenerAdapter实例化
@Bean
RedisMessageListenerContainer container(@Qualifier("getRedisConnectionFactory") RedisConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("chat")); return container;
} @Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
//通过Receiver实例化Adapter,设置默认listen方法,receiveMessage
return new MessageListenerAdapter(receiver, "receiveMessage");
} @Bean
Receiver receiver(CountDownLatch latch) {
return new Receiver(latch);
} @Bean
CountDownLatch latch() {
return new CountDownLatch(100);//设置上限100
} //StringRedisTemplate由RedisConnectionFactory实例化
@Bean
StringRedisTemplate template(@Qualifier("getRedisConnectionFactory") RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
} public static void main(String[] args) throws InterruptedException {
ApplicationContext ctx = SpringApplication.run(Application.class, args); CountDownLatch latch = ctx.getBean(CountDownLatch.class);
latch.await();
System.exit(0);
}
}

这样Application就完成了。

  • RedisMessageListenerContainer由container方法返回。
  • MessageListenerAdapter 由listenAdapter方法返回,构造函数里面第二个参数表示调用的方法receiveMessage,这个在receiver类中已经定义。
  • StringRedisTemplate 由template方法返回,这个类关注于操作key和value都是String类型的数据。

创建一个webapi来测试这个功能

src/main/java/hello/controller/TestController.java

/*
* Copyright (c) 2019.
* lou
*/ package hello.controller; import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import java.util.Random; @RestController
public class TestController {
Random random = new Random();
StringRedisTemplate template; public TestController(StringRedisTemplate template) {
this.template = template;
} @GetMapping("test")
public int TestMethod(@RequestParam(name = "t", defaultValue = "hello") String t) {
ValueOperations operations = template.opsForValue();
//测试读写redis
operations.set("t", t);
//发送消息
template.convertAndSend("chat", "消息" + t); return random.nextInt(100);
}
}

test方法里面调用convertAndSend方法,发送消息,启动后访问http://localhost:8080/test?t=2432,可以看到日志上有返回内容。

构建可执行jar

打包 mvn package

运行 java -jar ./target/xxx.jar。看到可以运行起来。

小结

这个demo教了我们如何通过配置文件配置redis连接,然后实现发布和订阅。

[SpingBoot guides系列翻译]Redis的消息订阅发布的更多相关文章

  1. 基于Redis的消息订阅/发布

    在工业生产设计中,我们往往需要实现一个基于消息订阅的模式,用来对非定时的的消息进行监听订阅. 这种设计模式在 总线设计模式中得到体现.微软以前的WCF中实现了服务总线 ServiceBus的设计模式. ...

  2. SpringBoot+Redis 实现消息订阅发布

    什么是 Redis Redis 是一个开源的使用 ANSI C语言编写的内存数据库,它以 key-value 键值对的形式存储数据,高性能,读取速度快,也提供了持久化存储机制. Redis 通常在项目 ...

  3. [SpingBoot guides系列翻译]文件上传

    文件上传 这节的任务是做一个文件上传服务. 概况 参考链接 原文 thymeleaf spring-mvc-flash-attributes @ControllerAdvice 你构建的内容 分两部分 ...

  4. Redis的消息订阅/发布 Utils工具类

    package cn.cicoding.utils; import org.json.JSONException; import org.json.JSONObject; import redis.c ...

  5. Redis之Redis消息订阅发布简介

    概念: Redis消息订阅发布是进程间的一种消息通信模式,发送者pub发送消息,订阅者sub接收消息. 使用须知: 需要先订阅后发布,才能接收到消息.在订阅时,相当于创建了可供发布的频道. 案例: ( ...

  6. Redis实现消息的发布/订阅

    利用spring-boot结合redis进行消息的发布与订阅: 发布: class Publish { private static String topicName = “Topic:chat”; ...

  7. 基于redis的消息订阅与发布

    Redis 的 SUBSCRIBE 命令可以让客户端订阅任意数量的频道, 每当有新信息发送到被订阅的频道时, 信息就会被发送给所有订阅指定频道的客户端. 作为例子, 下图展示了频道 channel1  ...

  8. Redis的消息订阅及发布及事务机制

    Redis的消息订阅及发布及事务机制 订阅发布 SUBSCRIBE PUBLISH 订阅消息队列及发布消息. # 首先要打开redis-cli shell窗口 一个用于消息发布 一个用于消息订阅 # ...

  9. spring boot: 用redis的消息订阅功能更新应用内的caffeine本地缓存(spring boot 2.3.2)

    一,为什么要更新caffeine缓存? 1,caffeine缓存的优点和缺点 生产环境中,caffeine缓存是我们在应用中使用的本地缓存, 它的优势在于存在于应用内,访问速度最快,通常都不到1ms就 ...

随机推荐

  1. 算法与数据结构基础 - 数组(Array)

    数组基础 数组是最基础的数据结构,特点是O(1)时间读取任意下标元素,经常应用于排序(Sort).双指针(Two Pointers).二分查找(Binary Search).动态规划(DP)等算法.顺 ...

  2. vs2010,vs2013,vs2015,vs2017, vs2019激活秘钥

    vs2010============================================== YCFHQ9DWCYDKV88T2TMHG7BHP vs2013=============== ...

  3. 发布Jar包到中央仓库

    参考流程 https://blog.csdn.net/qq_36838191/article/details/81027586 备份还原 gpg-keys https://blog.rathena.c ...

  4. ROS kinetic + Realsens D435i + ORK + LINEMOD 物体识别

    1. ORK 网址:https://wg-perception.github.io/object_recognition_core/ ORK (Object Recognition Kitchen) ...

  5. source vimrc的时候报错:.vimrc:1: command not found: syntax

    vim的配置如下: 1 syntax enable //语法高亮 2 set number //显示行号 3 set cursorline //突出显示当前行 4 set ruler //打开状态栏标 ...

  6. 1+x 证书 Web 前端开发中级理论考试(试卷 7 ) 答案

    1+x 证书 Web 前端开发中级理论考试(试卷 7 ) 答案 转载请注明来源:妙笔生花个人博客http://blog.zh66.club/index.php/archives/438/ 官方QQ群 ...

  7. Unity 利用Cinemachine快速创建灵活的相机系统

    在第一或第三人称ACT和FPS游戏中,相机的运动需求是多种多样的,Unity内置的Cinemachine包可以助你快速实现不同相机功能,例如范围追踪,边界设置等. 例如,考虑这样一个功能,这在很多游戏 ...

  8. idea插件备份

  9. php中trait的使用方法

    1.php中的trait是啥? 看上去既像类又像接口,其实都不是,Trait可以看做类的部分实现,可以混入一个或多个现有的PHP类中,其作用有两个:表明类可以做什么:提供模块化实现.Trait是一种代 ...

  10. hibernate关联关系(一对多)

    什么是关联(association) 关联指的是类之间的引用关系.如果类A与类B关联,那么被引用的类B将被定义为类A的属性. 案例:如何建立客户和订单一对多双向关联 先不建立客户和订单的关联关系,定义 ...