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. node 下载 md5.js

    命令:npm install js-md5

  2. 纠错:Feign 没用 短连接

    Feign 默认不是 短连接 疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 疯狂创客圈(笔者尼恩创建的高并发研习社群)Springcloud 高并发系列文章,将为大 ...

  3. app自动化测试环境搭建之node+appium+ADT+MUMU模拟器

    一.安装Microsoft .NET Framework 4.5 检测本机已安装的程序中,是否已经安装Microsoft .NET Framework 4.5及以上的版本 如果没有安装,则获取安装文件 ...

  4. Spring Cloud Alibaba基础教程:Sentinel Dashboard同步Apollo存储规则

    在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nacos和Apollo中.同时,在文末的思考中,我都指出了这两套整合方案都存在一个不足之处:不论采用什么配置中心,限流规则都只能 ...

  5. Token ,Cookie、Session傻傻分不清楚?

    作者 | 王菜鸟1993 来源 | cnblogs.com/JamesWang1993/p/8593494.html 在做接口测试时,经常会碰到请求参数为token的类型,但是可能大部分测试人员对to ...

  6. Java开发桌面程序学习(一)——JavaFx+Jfoenix初始以及搭建

    Java开发桌面程序学习(一)--JavaFx+Jfoenix初始以及搭建 前言 想做一个Java的桌面程序,但是,使用原生的Swing感觉又十分麻烦,那个布局都是拿代码设置,看着十分的乱,偶然的情况 ...

  7. Python爬取上交所一年大盘数据

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 半个码农2018 PS:如有需要Python学习资料的小伙伴可以加点 ...

  8. 并发编程-epoll模型的探索与实践

    前言 我们知道nginx的效率非常高,能处理上万级的并发,其之所以高效离不开epoll的支持, epoll是什么呢?,epoll是IO模型中的一种,属于多路复用IO模型; 到这里你应该想到了,sele ...

  9. Django---SETTINGS配置(***)

    Django---SETTINGS核心配置项 django核心配置项 Django的默认配置文件中,包含上百条配置项目,其中很多是我们'一辈子'都不碰到或者不需要单独配置的,这些项目在需要的时候再去查 ...

  10. C++ 手把手教你实现可变长的数组

    01 实现自定义的可变长数组类型 假设我们要实现一个会自动扩展的数组,要实现什么函数呢?先从下面的main函数给出的实现,看看有什么函数是需要我们实现的. int main() { MyArray a ...