提交 79bc227c 编写于 作者: R Rossen Stoyanchev

Remove SimpleResultHandler

There is really no need for a result handler dedicated to a void
return value and it's actually problematic to have it.

Each result handler treats void as necessary. For an @ResponseBody
method it means an empty body. For view resolution it means no specific
value was returned and we should procede with selecting a default view
name. Having a dedicated void result handler can interfere with this
especially since view resolution needs to be last in order.

At the same time there are cases when no result handling is needed
and the response is fully handled within the HandlerAdapter. This is
the case with WebHandler and the SimpleHandlerAdapter. For that case
we simply return mono.then(aVoid -> Mono.empty()) which effectively
returns an empty Mono and no result handling follows. The
HandlerAdapter already says you can return no values at all if the
response is fully handled.
上级 328e04f1
......@@ -55,7 +55,6 @@ import org.springframework.validation.Validator;
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
import org.springframework.web.reactive.result.SimpleHandlerAdapter;
import org.springframework.web.reactive.result.SimpleResultHandler;
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
......@@ -321,11 +320,6 @@ public class WebReactiveConfiguration implements ApplicationContextAware {
return new SimpleHandlerAdapter();
}
@Bean
public SimpleResultHandler simpleResultHandler() {
return new SimpleResultHandler();
}
@Bean
public ResponseEntityResultHandler responseEntityResultHandler() {
return new ResponseEntityResultHandler(getMessageWriters(), mvcContentTypeResolver());
......
......@@ -60,7 +60,7 @@ public class SimpleHandlerAdapter implements HandlerAdapter {
public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
WebHandler webHandler = (WebHandler) handler;
Mono<Void> mono = webHandler.handle(exchange);
return Mono.just(new HandlerResult(webHandler, mono, RETURN_TYPE));
return mono.then(aVoid -> Mono.empty());
}
}
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.reactive.result;
import java.util.Optional;
import reactor.core.publisher.Mono;
import org.springframework.core.Ordered;
import org.springframework.core.ReactiveAdapter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.ResolvableType;
import org.springframework.util.Assert;
import org.springframework.web.reactive.HandlerResult;
import org.springframework.web.reactive.HandlerResultHandler;
import org.springframework.web.server.ServerWebExchange;
/**
* A simple handler for return values of type {@code void}, or
* {@code Publisher<Void>}, or if a {link ConversionService} is provided, also
* of any other async return value types that can be converted to
* {@code Publisher<Void>} such as {@code Observable<Void>} or
* {@code CompletableFuture<Void>}.
*
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
* @since 5.0
*/
public class SimpleResultHandler implements Ordered, HandlerResultHandler {
private ReactiveAdapterRegistry adapterRegistry;
private int order = Ordered.LOWEST_PRECEDENCE;
public SimpleResultHandler() {
this.adapterRegistry = new ReactiveAdapterRegistry();
}
public SimpleResultHandler(ReactiveAdapterRegistry adapterRegistry) {
Assert.notNull(adapterRegistry, "'adapterRegistry' is required.");
this.adapterRegistry = adapterRegistry;
}
/**
* Return the configured {@link ReactiveAdapterRegistry}.
*/
public ReactiveAdapterRegistry getAdapterRegistry() {
return this.adapterRegistry;
}
/**
* Set the order for this result handler relative to others.
* <p>By default this is set to {@link Ordered#LOWEST_PRECEDENCE} and is
* generally safe to use late in the order since it looks specifically for
* {@code void} or async return types parameterized by {@code void}.
* @param order the order
*/
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
@Override
public boolean supports(HandlerResult result) {
ResolvableType type = result.getReturnType();
Class<?> rawClass = type.getRawClass();
if (Void.TYPE.equals(rawClass)) {
return true;
}
ReactiveAdapter adapter = getAdapterRegistry().getAdapterFrom(rawClass, result.getReturnValue());
if (adapter != null) {
Class<?> clazz = type.getGeneric(0).getRawClass();
return Void.class.equals(clazz);
}
return false;
}
@SuppressWarnings("unchecked")
@Override
public Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
Optional<Object> optionalValue = result.getReturnValue();
if (!optionalValue.isPresent()) {
return Mono.empty();
}
Class<?> returnType = result.getReturnType().getRawClass();
ReactiveAdapter adapter = getAdapterRegistry().getAdapterFrom(returnType, optionalValue);
return adapter.toMono(optionalValue);
}
}
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.reactive.result;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.junit.Before;
import org.junit.Test;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import rx.Observable;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.web.reactive.HandlerResult;
import static org.junit.Assert.assertEquals;
/**
* Unit tests for {@link SimpleResultHandler}.
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
*/
public class SimpleResultHandlerTests {
private SimpleResultHandler resultHandler;
@Before
public void setUp() throws Exception {
this.resultHandler = new SimpleResultHandler();
}
@Test
public void supports() throws NoSuchMethodException {
testSupports(ResolvableType.forClass(void.class), true);
testSupports(ResolvableType.forClassWithGenerics(Publisher.class, Void.class), true);
testSupports(ResolvableType.forClassWithGenerics(Flux.class, Void.class), true);
testSupports(ResolvableType.forClassWithGenerics(Observable.class, Void.class), true);
testSupports(ResolvableType.forClassWithGenerics(CompletableFuture.class, Void.class), true);
testSupports(ResolvableType.forClass(String.class), false);
testSupports(ResolvableType.forClassWithGenerics(Publisher.class, String.class), false);
}
@Test
public void supportsUsesGenericTypeInformation() throws Exception {
testSupports(ResolvableType.forClassWithGenerics(List.class, Void.class), false);
}
private void testSupports(ResolvableType type, boolean result) {
MethodParameter param = ResolvableMethod.onClass(TestController.class).returning(type).resolveReturnType();
HandlerResult handlerResult = new HandlerResult(new TestController(), null, param);
assertEquals(result, this.resultHandler.supports(handlerResult));
}
@SuppressWarnings("unused")
private static class TestController {
public void voidReturn() { }
public Publisher<String> publisherString() { return null; }
public Flux<Void> flux() { return null; }
public Observable<Void> observable() { return null; }
public CompletableFuture<Void> completableFuture() { return null; }
public String string() { return null; }
public Publisher<Void> publisher() { return null; }
public List<Void> list() { return null; }
}
}
......@@ -143,11 +143,6 @@ public class SimpleUrlHandlerMappingIntegrationTests extends AbstractHttpHandler
public SimpleHandlerAdapter handlerAdapter() {
return new SimpleHandlerAdapter();
}
@Bean
public SimpleResultHandler resultHandler() {
return new SimpleResultHandler();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册