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. vscode源码分析【七】主进程启动消息通信服务

    第一篇: vscode源码分析[一]从源码运行vscode 第二篇:vscode源码分析[二]程序的启动逻辑,第一个窗口是如何创建的 第三篇:vscode源码分析[三]程序的启动逻辑,性能问题的追踪 ...

  2. 如何创建Azure Face API和计算机视觉Computer Vision API

    在人工智能技术飞速发展的当前,利用技术手段实现人脸识别.图片识别已经不是什么难事.目前,百度.微软等云计算厂商均推出了人脸识别和计算机视觉的API,其优势在于不需要搭建本地环境,只需要通过网络交互,就 ...

  3. Linux 小工具

    1. 截图工具 shutter 安装 sudo add-apt-repository ppa:shutter/ppa sudo apt-get update sudo apt-get install ...

  4. Linux 下编写一个 PHP 扩展

        假设需求 开发一个叫做 helloWord 的扩展. 扩展里有一个函数,helloWord(). echo helloWord('Tom'); //返回:Hello World: Tom 本地 ...

  5. json递归查询

    主体: class json_search(): '''递归查询依赖key''' def search_key(self,data,key): self.data = data self.key_va ...

  6. Linux Ubuntu 16.04 安装步骤+远程环境

    简介 Ubantu 16.04 系统是一款比较稳定的linux系统,适合用户使用以及针对一些兼容性的服务搭建. 这里我推荐安装桌面版,用于方便使用. 准备工作 1.准备1个U盘空间5G以上 2.需下载 ...

  7. C# event

    class Program { static void Main(string[] args) { Thermostat thermostat = new Thermostat(); Heater h ...

  8. c#中xml增删查改

    /// <summary> /// xml转list /// </summary> /// <typeparam name="T">目标对象&l ...

  9. 13. 罗马数字转整数(C#)

    看到这道题,存在键值对,所以先建个泛型字典,把键值填进去. 由于这道题存在两个字符表示一个数字的情况,所以在for循环的时候判断一下,看看当前字符串中循环到的字符是否和下一个字符能够组成存在在字典里的 ...

  10. 2019 Python100道 面试 题,你会几道?

    0 遇到过得反爬虫策略以及解决方法? 1.通过headers反爬虫 2.基于用户行为的发爬虫:(同一IP短时间内访问的频率) 3.动态网页反爬虫(通过ajax请求数据,或者通过JavaScript生成 ...