Polish
This commit is contained in:
		
							parent
							
								
									8f78c772b5
								
							
						
					
					
						commit
						bc470fca30
					
				| 
						 | 
					@ -243,13 +243,12 @@ public final class ModelFactory {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Derive the model attribute name for a method parameter based on:
 | 
						 * Derive the model attribute name for the given method parameter based on
 | 
				
			||||||
	 * <ol>
 | 
						 * a {@code @ModelAttribute} parameter annotation (if present) or falling
 | 
				
			||||||
	 * <li>the parameter {@code @ModelAttribute} annotation value
 | 
						 * back on parameter type based conventions.
 | 
				
			||||||
	 * <li>the parameter type
 | 
					 | 
				
			||||||
	 * </ol>
 | 
					 | 
				
			||||||
	 * @param parameter a descriptor for the method parameter
 | 
						 * @param parameter a descriptor for the method parameter
 | 
				
			||||||
	 * @return the derived name (never {@code null} or empty String)
 | 
						 * @return the derived name
 | 
				
			||||||
 | 
						 * @see Conventions#getVariableNameForParameter(MethodParameter)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public static String getNameForParameter(MethodParameter parameter) {
 | 
						public static String getNameForParameter(MethodParameter parameter) {
 | 
				
			||||||
		ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
 | 
							ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,10 +74,7 @@ public class SessionAttributesHandler {
 | 
				
			||||||
			this.attributeNames.addAll(Arrays.asList(annotation.names()));
 | 
								this.attributeNames.addAll(Arrays.asList(annotation.names()));
 | 
				
			||||||
			this.attributeTypes.addAll(Arrays.asList(annotation.types()));
 | 
								this.attributeTypes.addAll(Arrays.asList(annotation.types()));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							this.knownAttributeNames.addAll(this.attributeNames);
 | 
				
			||||||
		for (String attributeName : this.attributeNames) {
 | 
					 | 
				
			||||||
			this.knownAttributeNames.add(attributeName);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					@ -90,7 +87,7 @@ public class SessionAttributesHandler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Whether the attribute name or type match the names and types specified
 | 
						 * Whether the attribute name or type match the names and types specified
 | 
				
			||||||
	 * via {@code @SessionAttributes} in underlying controller.
 | 
						 * via {@code @SessionAttributes} on the underlying controller.
 | 
				
			||||||
	 * <p>Attributes successfully resolved through this method are "remembered"
 | 
						 * <p>Attributes successfully resolved through this method are "remembered"
 | 
				
			||||||
	 * and subsequently used in {@link #retrieveAttributes(WebRequest)} and
 | 
						 * and subsequently used in {@link #retrieveAttributes(WebRequest)} and
 | 
				
			||||||
	 * {@link #cleanupAttributes(WebRequest)}.
 | 
						 * {@link #cleanupAttributes(WebRequest)}.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2016 the original author or authors.
 | 
					 * Copyright 2002-2017 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -30,12 +30,15 @@ import org.springframework.web.bind.support.SessionAttributeStore;
 | 
				
			||||||
import org.springframework.web.context.request.NativeWebRequest;
 | 
					import org.springframework.web.context.request.NativeWebRequest;
 | 
				
			||||||
import org.springframework.web.context.request.ServletWebRequest;
 | 
					import org.springframework.web.context.request.ServletWebRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static java.util.Arrays.*;
 | 
					import static java.util.Arrays.asList;
 | 
				
			||||||
import static org.junit.Assert.*;
 | 
					import static org.junit.Assert.assertEquals;
 | 
				
			||||||
 | 
					import static org.junit.Assert.assertFalse;
 | 
				
			||||||
 | 
					import static org.junit.Assert.assertNotNull;
 | 
				
			||||||
 | 
					import static org.junit.Assert.assertNull;
 | 
				
			||||||
 | 
					import static org.junit.Assert.assertTrue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Test fixture with {@link SessionAttributesHandler}.
 | 
					 * Test fixture with {@link SessionAttributesHandler}.
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author Rossen Stoyanchev
 | 
					 * @author Rossen Stoyanchev
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class SessionAttributesHandlerTests {
 | 
					public class SessionAttributesHandlerTests {
 | 
				
			||||||
| 
						 | 
					@ -50,10 +53,10 @@ public class SessionAttributesHandlerTests {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
	public void isSessionAttribute() throws Exception {
 | 
						public void isSessionAttribute() throws Exception {
 | 
				
			||||||
		assertTrue(sessionAttributesHandler.isHandlerSessionAttribute("attr1", null));
 | 
							assertTrue(sessionAttributesHandler.isHandlerSessionAttribute("attr1", String.class));
 | 
				
			||||||
		assertTrue(sessionAttributesHandler.isHandlerSessionAttribute("attr2", null));
 | 
							assertTrue(sessionAttributesHandler.isHandlerSessionAttribute("attr2", String.class));
 | 
				
			||||||
		assertTrue(sessionAttributesHandler.isHandlerSessionAttribute("simple", TestBean.class));
 | 
							assertTrue(sessionAttributesHandler.isHandlerSessionAttribute("simple", TestBean.class));
 | 
				
			||||||
		assertFalse(sessionAttributesHandler.isHandlerSessionAttribute("simple", null));
 | 
							assertFalse(sessionAttributesHandler.isHandlerSessionAttribute("simple", String.class));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Test
 | 
						@Test
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,8 @@ import org.springframework.web.bind.support.WebExchangeDataBinder;
 | 
				
			||||||
import org.springframework.web.server.ServerWebExchange;
 | 
					import org.springframework.web.server.ServerWebExchange;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Context to assist with processing a request and binding it onto Objects.
 | 
					 * Context to assist with binding request data onto Objects and provide access
 | 
				
			||||||
 | 
					 * to a shared {@link Model} with controller-specific attributes.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * <p>Provides  methods to create a {@link WebExchangeDataBinder} for a specific
 | 
					 * <p>Provides  methods to create a {@link WebExchangeDataBinder} for a specific
 | 
				
			||||||
 * target, command Object to apply data binding and validation to, or without a
 | 
					 * target, command Object to apply data binding and validation to, or without a
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,7 @@ import org.springframework.core.ReactiveAdapter;
 | 
				
			||||||
import org.springframework.core.ReactiveAdapterRegistry;
 | 
					import org.springframework.core.ReactiveAdapterRegistry;
 | 
				
			||||||
import org.springframework.core.ResolvableType;
 | 
					import org.springframework.core.ResolvableType;
 | 
				
			||||||
import org.springframework.core.annotation.AnnotatedElementUtils;
 | 
					import org.springframework.core.annotation.AnnotatedElementUtils;
 | 
				
			||||||
 | 
					import org.springframework.lang.Nullable;
 | 
				
			||||||
import org.springframework.util.StringUtils;
 | 
					import org.springframework.util.StringUtils;
 | 
				
			||||||
import org.springframework.web.bind.annotation.ModelAttribute;
 | 
					import org.springframework.web.bind.annotation.ModelAttribute;
 | 
				
			||||||
import org.springframework.web.reactive.BindingContext;
 | 
					import org.springframework.web.reactive.BindingContext;
 | 
				
			||||||
| 
						 | 
					@ -73,12 +74,13 @@ class ModelInitializer {
 | 
				
			||||||
		List<Mono<HandlerResult>> resultList = new ArrayList<>();
 | 
							List<Mono<HandlerResult>> resultList = new ArrayList<>();
 | 
				
			||||||
		attributeMethods.forEach(invocable -> resultList.add(invocable.invoke(exchange, bindingContext)));
 | 
							attributeMethods.forEach(invocable -> resultList.add(invocable.invoke(exchange, bindingContext)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return Mono.zip(resultList, objectArray -> {
 | 
							return Mono
 | 
				
			||||||
 | 
									.zip(resultList, objectArray -> {
 | 
				
			||||||
					return Arrays.stream(objectArray)
 | 
										return Arrays.stream(objectArray)
 | 
				
			||||||
					.map(object -> (HandlerResult) object)
 | 
												.map(object -> handleResult(((HandlerResult) object), bindingContext))
 | 
				
			||||||
					.map(handlerResult -> handleResult(handlerResult, bindingContext))
 | 
					 | 
				
			||||||
							.collect(Collectors.toList());
 | 
												.collect(Collectors.toList());
 | 
				
			||||||
		}).flatMap(completionList -> Mono.when(completionList));
 | 
									})
 | 
				
			||||||
 | 
									.flatMap(completionList -> Mono.when(completionList));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private Mono<Void> handleResult(HandlerResult handlerResult, BindingContext bindingContext) {
 | 
						private Mono<Void> handleResult(HandlerResult handlerResult, BindingContext bindingContext) {
 | 
				
			||||||
| 
						 | 
					@ -86,18 +88,19 @@ class ModelInitializer {
 | 
				
			||||||
		if (value != null) {
 | 
							if (value != null) {
 | 
				
			||||||
			ResolvableType type = handlerResult.getReturnType();
 | 
								ResolvableType type = handlerResult.getReturnType();
 | 
				
			||||||
			ReactiveAdapter adapter = this.adapterRegistry.getAdapter(type.getRawClass(), value);
 | 
								ReactiveAdapter adapter = this.adapterRegistry.getAdapter(type.getRawClass(), value);
 | 
				
			||||||
			if (adapter != null) {
 | 
								if (isAsyncVoidType(type, adapter)) {
 | 
				
			||||||
				Class<?> attributeType = (adapter.isNoValue() ? Void.class : type.resolveGeneric());
 | 
					 | 
				
			||||||
				if (attributeType == Void.class) {
 | 
					 | 
				
			||||||
				return Mono.from(adapter.toPublisher(value));
 | 
									return Mono.from(adapter.toPublisher(value));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			String name = getAttributeName(handlerResult.getReturnTypeSource());
 | 
								String name = getAttributeName(handlerResult.getReturnTypeSource());
 | 
				
			||||||
			bindingContext.getModel().asMap().putIfAbsent(name, value);
 | 
								bindingContext.getModel().asMap().putIfAbsent(name, value);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return Mono.empty();
 | 
							return Mono.empty();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private boolean isAsyncVoidType(ResolvableType type, @Nullable  ReactiveAdapter adapter) {
 | 
				
			||||||
 | 
							return adapter != null && (adapter.isNoValue() || type.resolveGeneric() == Void.class);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private String getAttributeName(MethodParameter param) {
 | 
						private String getAttributeName(MethodParameter param) {
 | 
				
			||||||
		return Optional
 | 
							return Optional
 | 
				
			||||||
				.ofNullable(AnnotatedElementUtils.findMergedAnnotation(param.getAnnotatedElement(), ModelAttribute.class))
 | 
									.ofNullable(AnnotatedElementUtils.findMergedAnnotation(param.getAnnotatedElement(), ModelAttribute.class))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,7 +147,6 @@ public abstract class AbstractView implements View, ApplicationContextAware {
 | 
				
			||||||
	 * Obtain the ApplicationContext for actual use.
 | 
						 * Obtain the ApplicationContext for actual use.
 | 
				
			||||||
	 * @return the ApplicationContext (never {@code null})
 | 
						 * @return the ApplicationContext (never {@code null})
 | 
				
			||||||
	 * @throws IllegalStateException in case of no ApplicationContext set
 | 
						 * @throws IllegalStateException in case of no ApplicationContext set
 | 
				
			||||||
	 * @since 5.0
 | 
					 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	protected final ApplicationContext obtainApplicationContext() {
 | 
						protected final ApplicationContext obtainApplicationContext() {
 | 
				
			||||||
		ApplicationContext applicationContext = getApplicationContext();
 | 
							ApplicationContext applicationContext = getApplicationContext();
 | 
				
			||||||
| 
						 | 
					@ -191,7 +190,9 @@ public abstract class AbstractView implements View, ApplicationContextAware {
 | 
				
			||||||
	 * <p>The default implementation creates a combined output Map that includes
 | 
						 * <p>The default implementation creates a combined output Map that includes
 | 
				
			||||||
	 * model as well as static attributes with the former taking precedence.
 | 
						 * model as well as static attributes with the former taking precedence.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	protected Mono<Map<String, Object>> getModelAttributes(@Nullable Map<String, ?> model, ServerWebExchange exchange) {
 | 
						protected Mono<Map<String, Object>> getModelAttributes(@Nullable Map<String, ?> model,
 | 
				
			||||||
 | 
								ServerWebExchange exchange) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int size = (model != null ? model.size() : 0);
 | 
							int size = (model != null ? model.size() : 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Map<String, Object> attributes = new LinkedHashMap<>(size);
 | 
							Map<String, Object> attributes = new LinkedHashMap<>(size);
 | 
				
			||||||
| 
						 | 
					@ -203,9 +204,11 @@ public abstract class AbstractView implements View, ApplicationContextAware {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * By default, resolve async attributes supported by the {@link ReactiveAdapterRegistry} to their blocking counterparts.
 | 
						 * By default, resolve async attributes supported by the
 | 
				
			||||||
	 * <p>View implementations capable of taking advantage of reactive types can override this method if needed.
 | 
						 * {@link ReactiveAdapterRegistry} to their blocking counterparts.
 | 
				
			||||||
	 * @return {@code Mono} to represent when the async attributes have been resolved
 | 
						 * <p>View implementations capable of taking advantage of reactive types
 | 
				
			||||||
 | 
						 * can override this method if needed.
 | 
				
			||||||
 | 
						 * @return {@code Mono} for the completion of async attributes resolution
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	protected Mono<Void> resolveAsyncAttributes(Map<String, Object> model) {
 | 
						protected Mono<Void> resolveAsyncAttributes(Map<String, Object> model) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -252,8 +255,9 @@ public abstract class AbstractView implements View, ApplicationContextAware {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Create a RequestContext to expose under the specified attribute name.
 | 
						 * Create a RequestContext to expose under the specified attribute name.
 | 
				
			||||||
	 * <p>The default implementation creates a standard RequestContext instance for the
 | 
						 * <p>The default implementation creates a standard RequestContext instance
 | 
				
			||||||
	 * given request and model. Can be overridden in subclasses for custom instances.
 | 
						 * for the given request and model. Can be overridden in subclasses for
 | 
				
			||||||
 | 
						 * custom instances.
 | 
				
			||||||
	 * @param exchange current exchange
 | 
						 * @param exchange current exchange
 | 
				
			||||||
	 * @param model combined output Map (never {@code null}),
 | 
						 * @param model combined output Map (never {@code null}),
 | 
				
			||||||
	 * with dynamic values taking precedence over static attributes
 | 
						 * with dynamic values taking precedence over static attributes
 | 
				
			||||||
| 
						 | 
					@ -269,7 +273,8 @@ public abstract class AbstractView implements View, ApplicationContextAware {
 | 
				
			||||||
	 * <p>The default implementation looks in the {@link #getApplicationContext()
 | 
						 * <p>The default implementation looks in the {@link #getApplicationContext()
 | 
				
			||||||
	 * Spring configuration} for a {@code RequestDataValueProcessor} bean with
 | 
						 * Spring configuration} for a {@code RequestDataValueProcessor} bean with
 | 
				
			||||||
	 * the name {@link #REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME}.
 | 
						 * the name {@link #REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME}.
 | 
				
			||||||
	 * @return the RequestDataValueProcessor, or null if there is none at the application context.
 | 
						 * @return the RequestDataValueProcessor, or null if there is none at the
 | 
				
			||||||
 | 
						 * application context.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	@Nullable
 | 
						@Nullable
 | 
				
			||||||
	protected RequestDataValueProcessor getRequestDataValueProcessor() {
 | 
						protected RequestDataValueProcessor getRequestDataValueProcessor() {
 | 
				
			||||||
| 
						 | 
					@ -286,7 +291,8 @@ public abstract class AbstractView implements View, ApplicationContextAware {
 | 
				
			||||||
	 * with dynamic values taking precedence over static attributes
 | 
						 * with dynamic values taking precedence over static attributes
 | 
				
			||||||
	 * @param contentType the content type selected to render with which should
 | 
						 * @param contentType the content type selected to render with which should
 | 
				
			||||||
	 * match one of the {@link #getSupportedMediaTypes() supported media types}.
 | 
						 * match one of the {@link #getSupportedMediaTypes() supported media types}.
 | 
				
			||||||
	 *@param exchange current exchange  @return {@code Mono} to represent when and if rendering succeeds
 | 
						 *@param exchange current exchange  @return {@code Mono} to represent when
 | 
				
			||||||
 | 
						 * and if rendering succeeds
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	protected abstract Mono<Void> renderInternal(Map<String, Object> renderAttributes,
 | 
						protected abstract Mono<Void> renderInternal(Map<String, Object> renderAttributes,
 | 
				
			||||||
			@Nullable MediaType contentType, ServerWebExchange exchange);
 | 
								@Nullable MediaType contentType, ServerWebExchange exchange);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue