Add ConcurrentModel

This commit adds a Model implementation based on ConcurrentHashMap for
use in Spring Web Reactive.

Issue: SPR-14542
This commit is contained in:
Rossen Stoyanchev
2016-11-02 15:25:05 +02:00
parent 9b57437b7a
commit 3230ca6d39
10 changed files with 237 additions and 27 deletions

View File

@@ -23,8 +23,8 @@ import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.ModelMap;
import org.springframework.ui.ConcurrentModel;
import org.springframework.ui.Model;
import org.springframework.util.Assert;
/**
@@ -42,7 +42,7 @@ public class HandlerResult {
private final ResolvableType returnType;
private final ModelMap model;
private final Model model;
private Function<Throwable, Mono<HandlerResult>> exceptionHandler;
@@ -64,13 +64,13 @@ public class HandlerResult {
* @param returnType the return value type
* @param model the model used for request handling
*/
public HandlerResult(Object handler, Object returnValue, MethodParameter returnType, ModelMap model) {
public HandlerResult(Object handler, Object returnValue, MethodParameter returnType, Model model) {
Assert.notNull(handler, "'handler' is required");
Assert.notNull(returnType, "'returnType' is required");
this.handler = handler;
this.returnValue = Optional.ofNullable(returnValue);
this.returnType = ResolvableType.forMethodParameter(returnType);
this.model = (model != null ? model : new ExtendedModelMap());
this.model = (model != null ? model : new ConcurrentModel());
}
@@ -107,7 +107,7 @@ public class HandlerResult {
* Return the model used during request handling with attributes that may be
* used to render HTML templates with.
*/
public ModelMap getModel() {
public Model getModel() {
return this.model;
}

View File

@@ -15,9 +15,8 @@
*/
package org.springframework.web.reactive.result.method;
import org.springframework.beans.TypeConverter;
import org.springframework.ui.ModelMap;
import org.springframework.validation.support.BindingAwareModelMap;
import org.springframework.ui.Model;
import org.springframework.validation.support.BindingAwareConcurrentModel;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.WebExchangeDataBinder;
import org.springframework.web.bind.support.WebBindingInitializer;
@@ -33,12 +32,10 @@ import org.springframework.web.server.ServerWebExchange;
*/
public class BindingContext {
private final ModelMap model = new BindingAwareModelMap();
private final Model model = new BindingAwareConcurrentModel();
private final WebBindingInitializer initializer;
private final TypeConverter simpleValueTypeConverter;
public BindingContext() {
this(null);
@@ -46,7 +43,6 @@ public class BindingContext {
public BindingContext(WebBindingInitializer initializer) {
this.initializer = initializer;
this.simpleValueTypeConverter = initTypeConverter(initializer);
}
private static WebExchangeDataBinder initTypeConverter(WebBindingInitializer initializer) {
@@ -61,7 +57,7 @@ public class BindingContext {
/**
* Return the default model.
*/
public ModelMap getModel() {
public Model getModel() {
return this.model;
}

View File

@@ -32,6 +32,7 @@ import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -101,7 +102,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
return resolveArguments(exchange, bindingContext, providedArgs).then(args -> {
try {
Object value = doInvoke(args);
ModelMap model = bindingContext.getModel();
Model model = bindingContext.getModel();
HandlerResult handlerResult = new HandlerResult(this, value, getReturnType(), model);
return Mono.just(handlerResult);
}

View File

@@ -27,7 +27,7 @@ import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.ui.ModelMap;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.reactive.result.method.BindingContext;
@@ -87,7 +87,7 @@ public abstract class AbstractNamedValueArgumentResolver implements HandlerMetho
"Specified name must not resolve to null: [" + namedValueInfo.name + "]"));
}
ModelMap model = bindingContext.getModel();
Model model = bindingContext.getModel();
return resolveName(resolvedName.toString(), nestedParameter, exchange)
.map(arg -> {
@@ -186,7 +186,7 @@ public abstract class AbstractNamedValueArgumentResolver implements HandlerMetho
}
private Mono<Object> getDefaultValue(NamedValueInfo namedValueInfo, MethodParameter parameter,
BindingContext bindingContext, ModelMap model, ServerWebExchange exchange) {
BindingContext bindingContext, Model model, ServerWebExchange exchange) {
Object value = null;
try {
@@ -263,7 +263,7 @@ public abstract class AbstractNamedValueArgumentResolver implements HandlerMetho
*/
@SuppressWarnings("UnusedParameters")
protected void handleResolvedValue(Object arg, String name, MethodParameter parameter,
ModelMap model, ServerWebExchange exchange) {
Model model, ServerWebExchange exchange) {
}

View File

@@ -22,7 +22,7 @@ import java.util.Optional;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.ui.ModelMap;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ValueConstants;
@@ -93,7 +93,7 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueSyncAr
@Override
@SuppressWarnings("unchecked")
protected void handleResolvedValue(Object arg, String name, MethodParameter parameter,
ModelMap model, ServerWebExchange exchange) {
Model model, ServerWebExchange exchange) {
// TODO: View.PATH_VARIABLES ?
}

View File

@@ -329,7 +329,7 @@ public class RequestMappingHandlerAdapter implements HandlerAdapter, BeanFactory
logger.debug("Invoking @ExceptionHandler method: " + invocable.getMethod());
}
invocable.setArgumentResolvers(getArgumentResolvers());
bindingContext.getModel().clear();
bindingContext.getModel().asMap().clear();
return invocable.invoke(exchange, bindingContext, ex);
}
catch (Throwable invocationEx) {

View File

@@ -206,7 +206,7 @@ public class ViewResolutionResultHandler extends AbstractHandlerResultHandler
.defaultIfEmpty(result.getModel())
.then(model -> getDefaultViewNameMono(exchange, result));
}
Map<String, ?> model = result.getModel();
Map<String, ?> model = result.getModel().asMap();
return viewMono.then(view -> {
updateResponseStatus(result.getReturnTypeSource(), exchange);
if (view instanceof View) {

View File

@@ -49,7 +49,6 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.reactive.HandlerResult;
@@ -80,7 +79,7 @@ public class ViewResolutionResultHandlerTests {
private ServerWebExchange exchange;
private ModelMap model = new ExtendedModelMap();
private Model model = new ExtendedModelMap();
@Before
@@ -184,7 +183,7 @@ public class ViewResolutionResultHandlerTests {
private void testDefaultViewName(Object returnValue, ResolvableType type)
throws URISyntaxException {
ModelMap model = new ExtendedModelMap().addAttribute("id", "123");
Model model = new ExtendedModelMap().addAttribute("id", "123");
HandlerResult result = new HandlerResult(new Object(), returnValue, returnType(type), model);
ViewResolutionResultHandler handler = createResultHandler(new TestViewResolver("account"));
@@ -290,7 +289,7 @@ public class ViewResolutionResultHandlerTests {
private void testHandle(String path, ResolvableMethod resolvableMethod, Object returnValue,
String responseBody, ViewResolver... resolvers) throws URISyntaxException {
ModelMap model = new ExtendedModelMap().addAttribute("id", "123");
Model model = new ExtendedModelMap().addAttribute("id", "123");
MethodParameter returnType = resolvableMethod.resolveReturnType();
HandlerResult result = new HandlerResult(new Object(), returnValue, returnType, model);
this.request.setUri(path);