Polish and update reactive getting started reference

This commit updates the instructions on getting started with
Spring Web Reactive and also updates constructors and setters to
streamline the getting started procedure.

Issue: SPR-14640
This commit is contained in:
Rossen Stoyanchev
2016-08-30 14:36:19 -04:00
parent 436486b8a1
commit 391752abc2
8 changed files with 70 additions and 53 deletions

View File

@@ -71,6 +71,14 @@ public class DispatcherHandler implements WebHandler, ApplicationContextAware {
private List<HandlerResultHandler> resultHandlers;
public DispatcherHandler() {
}
public DispatcherHandler(ApplicationContext applicationContext) {
initStrategies(applicationContext);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
initStrategies(applicationContext);

View File

@@ -87,8 +87,7 @@ public class DispatcherHandlerErrorTests {
appContext.register(TestConfig.class);
appContext.refresh();
this.dispatcherHandler = new DispatcherHandler();
this.dispatcherHandler.setApplicationContext(appContext);
this.dispatcherHandler = new DispatcherHandler(appContext);
this.request = new MockServerHttpRequest(HttpMethod.GET, new URI("/"));
MockServerHttpResponse response = new MockServerHttpResponse();

View File

@@ -61,10 +61,7 @@ public class SimpleUrlHandlerMappingIntegrationTests extends AbstractHttpHandler
wac.register(WebConfig.class);
wac.refresh();
DispatcherHandler dispatcherHandler = new DispatcherHandler();
dispatcherHandler.setApplicationContext(wac);
return WebHttpHandlerBuilder.webHandler(dispatcherHandler)
return WebHttpHandlerBuilder.webHandler(new DispatcherHandler(wac))
.exceptionHandlers(new ResponseStatusExceptionHandler())
.build();
}

View File

@@ -44,9 +44,9 @@ public abstract class AbstractRequestMappingIntegrationTests extends AbstractHtt
@Override
protected HttpHandler createHttpHandler() {
this.applicationContext = initApplicationContext();
DispatcherHandler handler = new DispatcherHandler();
handler.setApplicationContext(this.applicationContext);
return WebHttpHandlerBuilder.webHandler(handler).build();
return WebHttpHandlerBuilder
.webHandler(new DispatcherHandler(this.applicationContext))
.build();
}
protected abstract ApplicationContext initApplicationContext();

View File

@@ -65,10 +65,7 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
this.wac.register(TestConfiguration.class);
this.wac.refresh();
DispatcherHandler webHandler = new DispatcherHandler();
webHandler.setApplicationContext(this.wac);
return WebHttpHandlerBuilder.webHandler(webHandler).build();
return WebHttpHandlerBuilder.webHandler(new DispatcherHandler(this.wac)).build();
}
@Test

View File

@@ -23,6 +23,7 @@ import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.util.Assert;
/**
@@ -40,17 +41,20 @@ public class UndertowHttpHandlerAdapter implements io.undertow.server.HttpHandle
private final HttpHandler delegate;
private final DataBufferFactory dataBufferFactory;
private DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(false);
public UndertowHttpHandlerAdapter(HttpHandler delegate, DataBufferFactory dataBufferFactory) {
public UndertowHttpHandlerAdapter(HttpHandler delegate) {
Assert.notNull(delegate, "'delegate' is required");
Assert.notNull(dataBufferFactory, "'dataBufferFactory' must not be null");
this.delegate = delegate;
this.dataBufferFactory = dataBufferFactory;
}
public void setDataBufferFactory(DataBufferFactory dataBufferFactory) {
Assert.notNull(dataBufferFactory, "'dataBufferFactory' must not be null");
this.dataBufferFactory = dataBufferFactory;
}
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {

View File

@@ -19,8 +19,6 @@ package org.springframework.http.server.reactive.bootstrap;
import io.undertow.Undertow;
import io.undertow.server.HttpHandler;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.server.reactive.UndertowHttpHandlerAdapter;
import org.springframework.util.Assert;
@@ -31,19 +29,13 @@ public class UndertowHttpServer extends HttpServerSupport implements HttpServer
private Undertow server;
private DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
private boolean running;
public void setDataBufferFactory(DataBufferFactory dataBufferFactory) {
this.dataBufferFactory = dataBufferFactory;
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(getHttpHandler());
HttpHandler handler =
new UndertowHttpHandlerAdapter(getHttpHandler(), dataBufferFactory);
HttpHandler handler = new UndertowHttpHandlerAdapter(getHttpHandler());
this.server = Undertow.builder().addHttpListener(getPort(), getHost())
.setHandler(handler).build();
}

View File

@@ -153,8 +153,10 @@ Single<Account> response = webClient
[[web-reactive-getting-started-boot]]
=== Spring Boot Starter
The experimental Spring Boot Web Reactive starter available via http://start.spring.io
is the quickest way to get started. It does all the work so you can start
The
https://github.com/bclozel/spring-boot-web-reactive#spring-boot-web-reactive-starter[Spring Boot Web Reactive starter]
available via http://start.spring.io
is the fastest way to get started. It does all that's necessary so you can start
writing `@Controller` classes. By default it runs on Tomcat but the dependencies can
be changed as usual with Spring Boot to switch to a different runtime.
@@ -162,39 +164,57 @@ be changed as usual with Spring Boot to switch to a different runtime.
[[web-reactive-getting-started-manual]]
=== Manual Bootstrapping
It is also easy to get started by writing a few lines of code:
This section outlines the steps to get up and running without Spring Boot.
For dependencies start with `spring-web-reactive` and `spring-context`.
Then add `jackson-databind` and `io.netty:netty-buffer:4.1.3.Final`
(temporarily see https://jira.spring.io/browse/SPR-14528[SPR-14528]) for JSON support.
Lastly add the dependencies for one of the supported runtimes:
* Tomcat -- `org.apache.tomcat.embed:tomcat-embed-core`
* Jetty -- `org.eclipse.jetty:jetty-server` and `org.eclipse.jetty:jetty-servlet`
* Reactor Netty -- `io.projectreactor.ipc:reactor-netty`
* RxNetty -- `io.reactivex:rxnetty-common` and `io.reactivex:rxnetty-http`
* Undertow -- `io.undertow:undertow-core`
For the bootstrap code start with:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(WebReactiveConfiguration.class); // (1)
context.refresh();
DispatcherHandler dispatcherHandler = new DispatcherHandler(context); // (2)
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(dispatcherHandler).build();
----
The above loads default Spring Web Reactive config (1), then creates a
`DispatcherHandler`, the main class driving request processing (2), and adapts
it to `HttpHandler`, the lowest level Spring abstraction for reactive HTTP request handling.
An `HttpHandler` can then be installed in each supported runtime:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
AnnotationConfigApplicationContext context;
context = new AnnotationConfigApplicationContext();
context.register(WebReactiveConfiguration.class); // (1)
context.refresh();
// Tomcat and Jetty
HttpServlet servlet = new ServletHttpHandlerAdapter(httpHandler);
...
DispatcherHandler handler = new DispatcherHandler(); // (2)
handler.setApplicationContext(context);
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(handler).build();
// Reactor Netty
HttpServer server = HttpServer.create(host, port)
server.startAndAwait(new ServletHttpHandlerAdapter(httpHandler));
HttpServer server = new TomcatHttpServer(); // (3)
server.setPort(8080);
server.setHandler(httpHandler);
server.afterPropertiesSet();
server.start();
// RxNetty
HttpServer server = HttpServer.newServer(new InetSocketAddress(host, port))
server.startAndAwait(new RxNettyHttpHandlerAdapter(httpHandler));
// Undertow
Undertow.builder().addHttpListener(port, host)
.setHandler(new UndertowHttpHandlerAdapter(httpHandler))
.build()
----
The `WebReactiveConfiguration` at (1) is the Java config from `spring-web-reactive`
and is similar in purpose to the MVC Java config from `spring-webmvc`. It provides the
web framework configuration required to get started leaving you only to
declare your own `@Controller` beans.
The `DispatcherHandler` at (2) is the equivalent of the `DispatcherServlet` in Spring MVC.
The `HttpServer` at (3) is an abstraction from the
https://github.com/spring-projects/spring-framework/tree/master/spring-web/src/test/java/org/springframework/http/server/reactive/bootstrap[test sources]
of `spring-web-reactive` used for Spring Framework's own integration tests.
The abstraction comes with basic implementations for each supported runtime.
[[web-reactive-getting-started-M1]]
=== Extent of Support in 5.0 M1