秋天里第一个Demo——Spring Reactor
最近公司有一个消息推送的项目代码交接到了我手上。我熟悉代码的时候,发现项目中用到了 Reactor 的异步编码方式。所以就想稍稍做些了解
一、第一个Demo
-
首先可以去 https://start.springboot.io/ 创建一个简单的 Spring Boot Demo,然后下载解压。
-
先来简单看一下我的 Demo 项目的目录层级结构吧:
-
当启动应用时,调用
http://localhost:8080/api/test
,向eventHandler的topic发送User事件,监听器即可接收到相关的事件并处理。
1.1 Maven项目配置文件pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.reactor</groupId>
<artifactId>spring-reactor-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-reactor-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>1.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.2 Spring Boot的主程序
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
1.3 实体类 User
package com.example.reactor.demo.dto;
public class User {
private String firstName;
private String lastName;
private String address;
private String city;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "User{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", address='" + address + '\'' +
", city='" + city + '\'' +
'}';
}
}
1.4 将 Reactor 交给 Spring 管理
package com.example.reactor.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.Environment;
import reactor.core.Reactor;
import reactor.core.spec.Reactors;
@Configuration
public class ReactorConfig {
@Bean
public Environment reactorEnv() {
return new Environment();
}
@Bean
public Reactor createReactor() {
return Reactors.reactor()
.env(reactorEnv())
.dispatcher(Environment.THREAD_POOL)
.get();
}
}
1.5 控制器类
package com.example.reactor.demo.controller;
import com.example.reactor.demo.dto.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.Reactor;
import reactor.event.Event;
@RestController
@RequestMapping("/api")
public class ApiController {
@Autowired
private Reactor reactor;
@RequestMapping("/test")
public String test() {
User user = new User();
user.setFirstName("Chetan");
user.setLastName("Birajdar");
user.setAddress("410 S Hauser");
user.setCity("Los Angeles");
reactor.notify("eventHandler", Event.wrap(user));
System.out.println("Yeah, I sent something for you!!");
return "Sent";
}
}
通过 Reactor 的实例方法 notify
发送数据。
1.6 事件监听器
package com.example.reactor.demo.listener;
import com.example.reactor.demo.dto.User;
import com.example.reactor.demo.service.UserService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import reactor.core.Reactor;
import reactor.event.Event;
import reactor.function.Consumer;
import static reactor.event.selector.Selectors.$;
@Component
public class UserEventListener implements Consumer<Event<User>>, InitializingBean {
@Autowired
private UserService userService;
@Autowired
private Reactor reactor;
@Override
public void accept(Event<User> userEvent) {
userService.saveUser(userEvent.getData());
}
@Override
public void afterPropertiesSet() {
reactor.on($("eventHandler"), this);
}
}
指定接收者/消费者:通过 Reactor 的实例方法 on
将事件绑定到指定的监听器。
1.7 服务类 Service
package com.example.reactor.demo.service;
import com.example.reactor.demo.dto.User;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void saveUser(User data) {
System.out.println("Saving user: " + data);
}
}