HandlerMapping is now asynchronous
This commit is contained in:
parent
dc57e2621c
commit
d319edba28
|
@ -98,41 +98,33 @@ public class DispatcherHandler implements ReactiveHttpHandler, ApplicationContex
|
||||||
logger.debug("Processing " + request.getMethod() + " request for [" + request.getURI() + "]");
|
logger.debug("Processing " + request.getMethod() + " request for [" + request.getURI() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
Object handler = getHandler(request);
|
Publisher<Object> handlerPublisher = getHandler(request);
|
||||||
if (handler == null) {
|
if (handlerPublisher == null) {
|
||||||
// No exception handling mechanism yet
|
// No exception handling mechanism yet
|
||||||
response.setStatusCode(HttpStatus.NOT_FOUND);
|
response.setStatusCode(HttpStatus.NOT_FOUND);
|
||||||
response.writeHeaders();
|
response.writeHeaders();
|
||||||
return Publishers.empty();
|
return Publishers.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Publisher<HandlerResult> resultPublisher = Publishers.concatMap(handlerPublisher, handler -> {
|
||||||
HandlerAdapter handlerAdapter = getHandlerAdapter(handler);
|
HandlerAdapter handlerAdapter = getHandlerAdapter(handler);
|
||||||
if (handlerAdapter == null) {
|
return handlerAdapter.handle(request, response, handler);
|
||||||
return Publishers.error(new IllegalStateException("No HandlerAdapter for " + handler));
|
});
|
||||||
}
|
|
||||||
|
|
||||||
Publisher<HandlerResult> resultPublisher = handlerAdapter.handle(request, response, handler);
|
|
||||||
|
|
||||||
return Publishers.concatMap(resultPublisher, result -> {
|
return Publishers.concatMap(resultPublisher, result -> {
|
||||||
for (HandlerResultHandler resultHandler : resultHandlers) {
|
HandlerResultHandler handler = getResultHandler(result);
|
||||||
if (resultHandler.supports(result)) {
|
return handler.handleResult(request, response, result);
|
||||||
return resultHandler.handleResult(request, response, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Publishers.error(new IllegalStateException(
|
|
||||||
"No HandlerResultHandler for " + result.getValue()));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Object getHandler(ReactiveServerHttpRequest request) {
|
protected Publisher<Object> getHandler(ReactiveServerHttpRequest request) {
|
||||||
Object handler = null;
|
|
||||||
for (HandlerMapping handlerMapping : this.handlerMappings) {
|
for (HandlerMapping handlerMapping : this.handlerMappings) {
|
||||||
handler = handlerMapping.getHandler(request);
|
Publisher<Object> handlerPublisher = handlerMapping.getHandler(request);
|
||||||
if (handler != null) {
|
if (handlerPublisher != null) {
|
||||||
break;
|
return handlerPublisher;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return handler;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HandlerAdapter getHandlerAdapter(Object handler) {
|
protected HandlerAdapter getHandlerAdapter(Object handler) {
|
||||||
|
@ -141,7 +133,16 @@ public class DispatcherHandler implements ReactiveHttpHandler, ApplicationContex
|
||||||
return handlerAdapter;
|
return handlerAdapter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
throw new IllegalStateException("No HandlerAdapter: " + handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HandlerResultHandler getResultHandler(HandlerResult handlerResult) {
|
||||||
|
for (HandlerResultHandler resultHandler : resultHandlers) {
|
||||||
|
if (resultHandler.supports(handlerResult)) {
|
||||||
|
return resultHandler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("No HandlerResultHandler: " + handlerResult.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.springframework.web.reactive;
|
package org.springframework.web.reactive;
|
||||||
|
|
||||||
|
import org.reactivestreams.Publisher;
|
||||||
|
|
||||||
import org.springframework.http.server.ReactiveServerHttpRequest;
|
import org.springframework.http.server.ReactiveServerHttpRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,6 +25,6 @@ import org.springframework.http.server.ReactiveServerHttpRequest;
|
||||||
*/
|
*/
|
||||||
public interface HandlerMapping {
|
public interface HandlerMapping {
|
||||||
|
|
||||||
Object getHandler(ReactiveServerHttpRequest request);
|
Publisher<Object> getHandler(ReactiveServerHttpRequest request);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ package org.springframework.web.reactive.handler;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.reactivestreams.Publisher;
|
||||||
|
import reactor.Publishers;
|
||||||
|
|
||||||
import org.springframework.http.server.ReactiveServerHttpRequest;
|
import org.springframework.http.server.ReactiveServerHttpRequest;
|
||||||
import org.springframework.web.reactive.HandlerMapping;
|
import org.springframework.web.reactive.HandlerMapping;
|
||||||
|
|
||||||
|
@ -39,8 +42,10 @@ public class SimpleUrlHandlerMapping implements HandlerMapping {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getHandler(ReactiveServerHttpRequest request) {
|
public Publisher<Object> getHandler(ReactiveServerHttpRequest request) {
|
||||||
return this.handlerMap.get(request.getURI().getPath());
|
String path = request.getURI().getPath();
|
||||||
|
Object handler = this.handlerMap.get(path);
|
||||||
|
return (handler != null ? Publishers.just(handler) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@ import java.util.TreeSet;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.reactivestreams.Publisher;
|
||||||
|
import reactor.Publishers;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
@ -92,15 +94,16 @@ public class RequestMappingHandlerMapping implements HandlerMapping,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getHandler(ReactiveServerHttpRequest request) {
|
public Publisher<Object> getHandler(ReactiveServerHttpRequest request) {
|
||||||
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : this.methodMap.entrySet()) {
|
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : this.methodMap.entrySet()) {
|
||||||
RequestMappingInfo info = entry.getKey();
|
RequestMappingInfo info = entry.getKey();
|
||||||
if (info.matchesRequest(request)) {
|
if (info.matchesRequest(request)) {
|
||||||
|
HandlerMethod handlerMethod = entry.getValue();
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Mapped " + request.getMethod() + " " +
|
logger.debug("Mapped " + request.getMethod() + " " +
|
||||||
request.getURI().getPath() + " to [" + entry.getValue() + "]");
|
request.getURI().getPath() + " to [" + handlerMethod + "]");
|
||||||
}
|
}
|
||||||
return entry.getValue();
|
return Publishers.just(handlerMethod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -19,10 +19,13 @@ package org.springframework.web.reactive.method.annotation;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.reactivestreams.Publisher;
|
import org.reactivestreams.Publisher;
|
||||||
|
import reactor.rx.Streams;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
@ -34,6 +37,7 @@ import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sebastien Deleuze
|
* @author Sebastien Deleuze
|
||||||
|
@ -56,19 +60,29 @@ public class RequestMappingHandlerMappingTests {
|
||||||
@Test
|
@Test
|
||||||
public void path() throws Exception {
|
public void path() throws Exception {
|
||||||
ReactiveServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "boo");
|
ReactiveServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "boo");
|
||||||
HandlerMethod handler = (HandlerMethod) this.mapping.getHandler(request);
|
Publisher<?> handlerPublisher = this.mapping.getHandler(request);
|
||||||
assertEquals(TestController.class.getMethod("boo"), handler.getMethod());
|
HandlerMethod handlerMethod = toHandlerMethod(handlerPublisher);
|
||||||
|
assertEquals(TestController.class.getMethod("boo"), handlerMethod.getMethod());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void method() throws Exception {
|
public void method() throws Exception {
|
||||||
ReactiveServerHttpRequest request = new MockServerHttpRequest(HttpMethod.POST, "foo");
|
ReactiveServerHttpRequest request = new MockServerHttpRequest(HttpMethod.POST, "foo");
|
||||||
HandlerMethod handler = (HandlerMethod) this.mapping.getHandler(request);
|
Publisher<?> handlerPublisher = this.mapping.getHandler(request);
|
||||||
assertEquals(TestController.class.getMethod("postFoo"), handler.getMethod());
|
HandlerMethod handlerMethod = toHandlerMethod(handlerPublisher);
|
||||||
|
assertEquals(TestController.class.getMethod("postFoo"), handlerMethod.getMethod());
|
||||||
|
|
||||||
request = new MockServerHttpRequest(HttpMethod.GET, "foo");
|
request = new MockServerHttpRequest(HttpMethod.GET, "foo");
|
||||||
handler = (HandlerMethod) this.mapping.getHandler(request);
|
handlerPublisher = this.mapping.getHandler(request);
|
||||||
assertEquals(TestController.class.getMethod("getFoo"), handler.getMethod());
|
handlerMethod = toHandlerMethod(handlerPublisher);
|
||||||
|
assertEquals(TestController.class.getMethod("getFoo"), handlerMethod.getMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
private HandlerMethod toHandlerMethod(Publisher<?> handlerPublisher) throws InterruptedException {
|
||||||
|
assertNotNull(handlerPublisher);
|
||||||
|
List<?> handlerList = Streams.wrap(handlerPublisher).toList().await(5, TimeUnit.SECONDS);
|
||||||
|
assertEquals(1, handlerList.size());
|
||||||
|
return (HandlerMethod) handlerList.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue