предисловие
Представлено вышемодель реактивного программированиясвязанные понятия, даSpring ReactorОсновнойAPIПодведен краткий итог. Эта статья будетSpring 5 WebFluxделать соответствующие презентации, в том числе знакомитьServlet 3.1 +, каждый функциональный компонентRouter Functions,WebFluxиReactive Streamsд., и какSpring Boot 2.0соответственно вГлобальная маршрутизация объектовиMVC контроллерспособ настройкиHTTPобработка запросов.
текст
Введение в Spring 5 WebFlux
оSpring 5изWebFluxРеактивное программирование, картинка ниже — традиционноеSpring Web MVCструктура иSpring 5Недавно добавлено на основеReactive StreamsизSpring WebFluxРамка. можно использоватьwebFluxмодули для сборкиАсинхронный,неблокирующий,управляемый событиямиуслуги, которыеМасштабируемостьВыступил очень хорошо.
как показано на рисунке,WebFluxМодули сверху внизRouter Functions,WebFlux,Reactive StreamsТри новых компонента.
Введение в API сервлетов 3.1+
WebFluxМодуль должен работать в реализацииServlet 3.1+ Спецификацияна контейнере.Servlet 3.1Добавлено в спецификациюАсинхронная обработкаподдержка в новомServletв спецификации,ServletТемы не должны бытьблокировка ожиданиядо завершения бизнес-процесса.
существуетServlet 3.1, потоковая модель обработки его запросов примерно такова:
-
ServletПосле того, как поток получает новый запрос, ему не нужно ждать завершения бизнес-обработки перед выводом результата, а он делегирует запрос другому потоку (бизнес-потоку) для завершения. -
ServletПоток вернется в контейнер после завершения делегирования для получения новых запросов.
Servlet 3.1Эта норма особенно применима кБизнес-обработка занимает много временипо сценарию может снизитьресурсы серверазаполняемость и увеличениеПараллельная скорость обработки, и для тех, кто можетБыстрый ответПольза от сцены невелика.
такWebFluxПоддерживаемые контейнерыTomcat,JettyЖдатьКонтейнер синхронизации,так же может бытьNettyиUndertowэтот видАсинхронный контейнер. в контейнереSpring WebFluxбудетвходной потокадаптирован кMonoилиFluxФормат унифицирован.
Функциональные модули для Spring WebFlux
Ниже описано изображение вышеWebFluxКаждый модуль:
1. Router Functions
по стандарту@Controller,@RequestMappingожидающийSpring MVCАннотация, предоставляющая наборфункциональный стильизAPI, создаватьRouter,HandlerиFilter.
2. WebFlux
Основные компоненты, координирующие предоставление вышестоящих и нижестоящих компонентовреактивное программированиеслужба поддержки.
3. Reactive Streams
поддержкаобратное давление (Backpressure)изСтандарт обработки асинхронных потоков данных, основная реализация имеетRxJavaиReactor,Spring WebFluxинтегрированныйReactor.
Flux
FluxиMonoпринадлежатьиздатель событий, похожий нарежиссер, потребителямПредоставить интерфейс подписки. Когда происходит событие,FluxилиMonoперезвонитпотребительсоответствующий способ уведомленияпотребительсоответствующее событие.
На картинке нижеFluxСхема рабочего процесса:
оFluxрабочий режим, видно чтоFluxможет вызвать(emit)полноitem, и этиitemможет пройти несколькоOperatorsа потом былsubscribe, используется следующееFluxПример:
Flux.fromIterable(getSomeLongList())
.mergeWith(Flux.interval(100))
.doOnNext(serviceA::someObserver)
.map(d -> d * 2)
.take(3)
.onErrorResumeWith(errorHandler::fallback)
.doAfterTerminate(serviceM::incrementTerminate)
.subscribe(System.out::println);
Mono
На картинке нижеMonoПроцесс обработки можно увидеть интуитивноMonoиFluxРазница:
Monoтолько триггер(emit)Одинitem, используется следующееMonoПример:
Mono.fromCallable(System::currentTimeMillis)
.flatMap(time -> Mono.first(serviceA.findRecent(time), serviceB.findRecent(time)))
.timeout(Duration.ofSeconds(3), errorHandler::fallback)
.doOnSuccess(r -> serviceM.incrementSuccess())
.subscribe(System.out::println);
Spring Boot 2.0 Reactive Stack
Spring Boot Webfluxоснован наReactorосуществленный.Spring Boot 2.0в том числе новыйspring-webfluxмодуль. Этот модуль содержитОтзывчивый HTTPиWebSocketподдержка клиентов, а такжеREST,HTMLиWebSocket интерактивные программыслужба поддержки. Вообще говоря,Spring MVCиспользуется дляСинхронная обработка,Spring Webfluxиспользуется дляАсинхронная обработка.
Как показано выше, изWebОт уровня представления к доступу к данным, к контейнеру,Spring Boot 2.0также обеспечиваетсинхронная блокировкаиАсинхронный неблокирующийдва полных комплектаAPI Stack.
Сравните различия между ними сверху вниз:
| API Stack | Sevlet Stack | Reactive Stack |
|---|---|---|
| Уровень веб-контроля | Spring MVC | Spring WebFlux |
| уровень аутентификации безопасности | Spring Security | Spring Security |
| уровень доступа к данным | Spring Data Repositories | Spring Data Reactive Repositories |
| API-интерфейс контейнера | Servlet API | Reactive Streams Adapters |
| встроенный контейнер | Servlet Containers | Netty, Servlet 3.1+ Containers |
Применимая сцена
Когда используется контрольный слойSpring WebFlux, необходимо использовать уровень аутентификации безопасности и уровень доступа к данным ниже него.Reactive API. Второй,Spring Data Reactive RepositoriesВ настоящее время поддерживается толькоMongoDB,RedisиCouchbaseНесколько других типов, которые не поддерживают управление транзакциямиNOSQL. Эти недостатки и риски необходимо взвешивать при выборе технологий, таких как:
-
Spring MVCЕсли он соответствует сцене, вам не нужно менять его наSpring WebFlux. -
Чтобы обратить внимание на поддержку контейнера, вы можете посмотреть на нижний слойвстроенный контейнерслужба поддержки.
-
МикросервисыАрхитектура,
Spring WebFluxиSpring MVCМожно смешать. особенно развитыйIOинтенсивныйПри подаче можно выбратьSpring WebFluxдостигать.
модель программирования
Spring 5 Webмодуль содержитSpring WebFluxизHTTPАннотация. похожийServlet API,WebFluxпри условииWebHandler APIопределятьнеблокирующий APIабстрактный интерфейс. Вы можете выбрать одну из следующих двух реализаций модели программирования:
-
Слой управления аннотациями:и
MVCбыть последовательным,WebFluxтакже поддерживаетОтветная реакция@RequestBodyаннотация. -
Функциональные конечные точки:на основе
lambdaОблегченная модель программирования длясоздать маршрутиобработать запросИнструмент. Самое большое отличие от вышеперечисленных заключается в том, что эта модель,весь процессконтрольответ на запросжизненный процесс
встроенный контейнер
иSpring BootЗапустите приложение как большую рамку, ноSpring WebFluxПо умолчаниюNettyзапускается и автоматически устанавливаетсяпорт по умолчаниюза8080. Также предоставляетJetty,Undertowи т.п. поддержка контейнера. Разработчик сам добавляет соответствующий контейнерStarterЗависимости компонентов можно настроить и использовать соответствующиеЭкземпляр встроенного контейнера.
Примечание: Должен быть контейнер Servlet 3.1+, такой как Tomcat, Jetty, или не-Servlet контейнер, такой как Netty и Undertow.
Стартовый компонент
иSpring Bootкак большая рамка,Spring Boot Webfluxобеспечивает многоиз коробкиизStarterкомпоненты. Добавить кspring-boot-starter-webfluxзависимости, его можно использовать для построенияОтзывчивый APIуслуги, которые включаютWebFluxиTomcat встроенный контейнерЖдать.
быстрый старт
Скелет проекта сборки Spring Initializr
использоватьSpring InitializerГенерировать быстроSpring BootПримените, настройте информацию о проекте и установите зависимости.
Настройка зависимостей Maven
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Класс запуска Spring Boot
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Настроить класс сущности
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Message {
String body;
}
1. Метод контроллера MVC
1.1 Написание контроллера
@RestController
@RequestMapping
public class MessageController {
@GetMapping
public Flux<Message> allMessages(){
return Flux.just(
Message.builder().body("hello Spring 5").build(),
Message.builder().body("hello Spring Boot 2").build()
);
}
}
1.2 Написание тестовых классов
@RunWith(SpringRunner.class)
@WebFluxTest(controllers = MessageController.class)
public class DemoApplicationTests {
@Autowired
WebTestClient client;
@Test
public void getAllMessagesShouldBeOk() {
client.get().uri("/").exchange().expectStatus().isOk();
}
}
1.3. Просмотр журнала запуска
2018-05-27 17:37:23.550 INFO 67749 --- [ main] s.w.r.r.m.a.RequestMappingHandlerMapping : Mapped "{[],methods=[GET]}" onto reactor.core.publisher.Flux<com.example.demo.Message> com.example.demo.MessageController.allMessages()
2018-05-27 17:37:23.998 INFO 67749 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2018-05-27 17:37:23.999 INFO 67749 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2018-05-27 17:37:24.003 INFO 67749 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 1.6 seconds (JVM running for 2.274)
Из лога видно, что:
- при запуске
WebFluxиспользоватьMVCоригинальныйRequestMappingHandlerMappingв контроллерепуть запросаиMVCсерединапроцессорсвязывать. -
Spring WebFluxПо умолчаниюNettyв видевстроенный контейнер, а порт запуска по умолчанию8080.
доступhttp://localhost:8080, возвращенный результат выглядит следующим образом:
2. Глобальный метод API маршрутизатора
2.1 Настройка глобального маршрутизатора Bean
@Configuration
public class DemoRouterConfig {
@Bean
public RouterFunction<ServerResponse> routes() {
return route(GET("/"), (ServerRequest req)-> ok()
.body(
BodyInserters.fromObject(
Arrays.asList(
Message.builder().body("hello Spring 5").build(),
Message.builder().body("hello Spring Boot 2").build()
)
)
)
);
}
}
2.2 Написание тестовых классов
@RunWith(SpringRunner.class)
@WebFluxTest
public class DemoApplicationTests {
@Autowired
WebTestClient client;
@Test
public void getAllMessagesShouldBeOk() {
client.get().uri("/").exchange().expectStatus().isOk();
}
}
2.3 Просмотр журнала запуска
бегатьSpring BootЗапустите класс записи, журнал запуска выглядит следующим образом (неважное опущено):
2018-05-27 17:20:28.870 INFO 67696 --- [ main] o.s.w.r.f.s.s.RouterFunctionMapping : Mapped (GET && /) -> com.example.demo.DemoRouterConfig$$Lambda$213/1561745898@3381b4fc
2018-05-27 17:20:28.931 INFO 67696 --- [ main] o.s.w.r.r.m.a.ControllerMethodResolver : Looking for @ControllerAdvice: org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext@1460a8c0: startup date [Sun May 27 17:20:27 CST 2018]; root of context hierarchy
2018-05-27 17:20:29.311 INFO 67696 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2018-05-27 17:20:29.312 INFO 67696 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2018-05-27 17:20:29.316 INFO 67696 --- [ main] com.example.demo.DemoApplication : Started DemoApplication in 2.137 seconds (JVM running for 3.169)
Как видно из лога: при запускеWebFluxиспользоватьRouterFunctionMappingбудетRouterFunctionвнутреннийглобальный путьиобработка запросаОтображение и привязка сделаны.
доступhttp://localhost:8080, возвращенный результат выглядит следующим образом:
Видно, что либо с помощьюFucntional Routerвсе ещеMVC Controller, может произвести тот же эффект!
Среда выполнения разработки
-
JDK 1.8 + :
Spring Boot 2.xТребоватьJDK 1.8среды и выше. Кроме того,Spring Boot 2.xтолько совместимыеSpring Framework 5.0и выше. -
Maven 3.2 +: за
Spring Boot 2.xПредоставляются соответствующие инструменты построения зависимостей.Maven, нужная версия3.2и выше. использоватьGradleтогда нужно1.12и выше.MavenиGradleКаждый может выбрать то, что ему нравится.
резюме
Эта статья впервыеSpring 5 WebFluxпредставлены отдельно, включая введениеServlet 3.1 +, каждый функциональный компонентRouter Functions,WebFluxиReactive StreamsЖдать. затем вSpring Boot 2.0подробно описаноReactive StackиServlet StackКомпозиционная разница , и даны соответственноWebFluxна основеГлобальная маршрутизация объектовиконтроллерконфигурация и варианты использования.
Добро пожаловать в технический публичный аккаунт: Zero One Technology Stack
Эта учетная запись будет продолжать делиться сухими товарами серверных технологий, включая основы виртуальных машин, многопоточное программирование, высокопроизводительные фреймворки, асинхронное ПО, промежуточное ПО для кэширования и обмена сообщениями, распределенные и микросервисы, материалы для обучения архитектуре и расширенные учебные материалы и статьи.