org.springframework.http.codec.DecoderHttpMessageReader#org.springframework.web.reactive.BindingContext源码实例Demo

下面列出了org.springframework.http.codec.DecoderHttpMessageReader#org.springframework.web.reactive.BindingContext 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

@Override
public Object resolveArgumentValue(
		MethodParameter parameter, BindingContext context, ServerWebExchange exchange) {

	Class<?> type = parameter.getParameterType();
	if (Model.class.isAssignableFrom(type)) {
		return context.getModel();
	}
	else if (Map.class.isAssignableFrom(type)) {
		return context.getModel().asMap();
	}
	else {
		// Should never happen..
		throw new IllegalStateException("Unexpected method parameter type: " + type);
	}
}
 
/**
 * Resolve the default value, if any.
 */
private Mono<Object> getDefaultValue(NamedValueInfo namedValueInfo, MethodParameter parameter,
		BindingContext bindingContext, Model model, ServerWebExchange exchange) {

	return Mono.fromSupplier(() -> {
		Object value = null;
		if (namedValueInfo.defaultValue != null) {
			value = resolveStringValue(namedValueInfo.defaultValue);
		}
		else if (namedValueInfo.required && !parameter.isOptional()) {
			handleMissingValue(namedValueInfo.name, parameter, exchange);
		}
		value = handleNullValue(namedValueInfo.name, value, parameter.getNestedParameterType());
		value = applyConversion(value, namedValueInfo, parameter, bindingContext, exchange);
		handleResolvedValue(value, namedValueInfo.name, parameter, model, exchange);
		return value;
	});
}
 
private void testHttpOptions(String requestURI, Set<HttpMethod> allowedMethods) {
	ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.options(requestURI));
	HandlerMethod handlerMethod = (HandlerMethod) this.handlerMapping.getHandler(exchange).block();

	BindingContext bindingContext = new BindingContext();
	InvocableHandlerMethod invocable = new InvocableHandlerMethod(handlerMethod);
	Mono<HandlerResult> mono = invocable.invoke(exchange, bindingContext);

	HandlerResult result = mono.block();
	assertNotNull(result);

	Object value = result.getReturnValue();
	assertNotNull(value);
	assertEquals(HttpHeaders.class, value.getClass());
	assertEquals(allowedMethods, ((HttpHeaders) value).getAllow());
}
 
/**
 * Invoke the method for the given exchange.
 * @param exchange the current exchange
 * @param bindingContext the binding context to use
 * @param providedArgs optional list of argument values to match by type
 * @return a Mono with a {@link HandlerResult}.
 * @throws ServerErrorException if method argument resolution or method invocation fails
 */
@Nullable
public HandlerResult invokeForHandlerResult(ServerWebExchange exchange,
		BindingContext bindingContext, Object... providedArgs) {

	MonoProcessor<HandlerResult> processor = MonoProcessor.create();
	this.delegate.invoke(exchange, bindingContext, providedArgs).subscribeWith(processor);

	if (processor.isTerminated()) {
		Throwable ex = processor.getError();
		if (ex != null) {
			throw (ex instanceof ServerErrorException ? (ServerErrorException) ex :
					new ServerErrorException("Failed to invoke: " + getShortLogMessage(), getMethod(), ex));
		}
		return processor.peek();
	}
	else {
		// Should never happen...
		throw new IllegalStateException(
				"SyncInvocableHandlerMethod should have completed synchronously.");
	}
}
 
@Test  // SPR-16158
public void resolveMonoParameter() {
	MethodParameter param = this.testMethod.annot(requestAttribute().noName()).arg(Mono.class, Foo.class);

	// Mono attribute
	Foo foo = new Foo();
	Mono<Foo> fooMono = Mono.just(foo);
	this.exchange.getAttributes().put("fooMono", fooMono);
	Mono<Object> mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange);
	assertSame(fooMono, mono.block(Duration.ZERO));

	// RxJava Single attribute
	Single<Foo> singleMono = Single.just(foo);
	this.exchange.getAttributes().clear();
	this.exchange.getAttributes().put("fooMono", singleMono);
	mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange);
	Object value = mono.block(Duration.ZERO);
	assertTrue(value instanceof Mono);
	assertSame(foo, ((Mono<?>) value).block(Duration.ZERO));

	// No attribute --> Mono.empty
	this.exchange.getAttributes().clear();
	mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange);
	assertSame(Mono.empty(), mono.block(Duration.ZERO));
}
 
@Test
public void resolverArgument() {

	BindingContext context = new BindingContext();
	WebSession session = mock(WebSession.class);
	MockServerHttpRequest request = MockServerHttpRequest.get("/").build();
	ServerWebExchange exchange = MockServerWebExchange.builder(request).session(session).build();

	MethodParameter param = this.testMethod.arg(WebSession.class);
	Object actual = this.resolver.resolveArgument(param, context, exchange).block();
	assertSame(session, actual);

	param = this.testMethod.arg(Mono.class, WebSession.class);
	actual = this.resolver.resolveArgument(param, context, exchange).block();
	assertNotNull(actual);
	assertTrue(Mono.class.isAssignableFrom(actual.getClass()));
	assertSame(session, ((Mono<?>) actual).block());

	param = this.testMethod.arg(Single.class, WebSession.class);
	actual = this.resolver.resolveArgument(param, context, exchange).block();
	assertNotNull(actual);
	assertTrue(Single.class.isAssignableFrom(actual.getClass()));
	assertSame(session, ((Single<?>) actual).blockingGet());
}
 
@Test
public void resolveOptional() throws Exception {
	MethodParameter param = this.testMethod.annot(requestAttribute().name("foo")).arg(Optional.class, Foo.class);
	Mono<Object> mono = this.resolver.resolveArgument(param, new BindingContext(), this.exchange);

	assertNotNull(mono.block());
	assertEquals(Optional.class, mono.block().getClass());
	assertFalse(((Optional<?>) mono.block()).isPresent());

	ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
	initializer.setConversionService(new DefaultFormattingConversionService());
	BindingContext bindingContext = new BindingContext(initializer);

	Foo foo = new Foo();
	this.exchange.getAttributes().put("foo", foo);
	mono = this.resolver.resolveArgument(param, bindingContext, this.exchange);

	assertNotNull(mono.block());
	assertEquals(Optional.class, mono.block().getClass());
	Optional<?> optional = (Optional<?>) mono.block();
	assertTrue(optional.isPresent());
	assertSame(foo, optional.get());
}
 
@Before
@SuppressWarnings("resource")
public void setup() throws Exception {
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
	context.refresh();

	ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
	this.resolver = new CookieValueMethodArgumentResolver(context.getBeanFactory(), adapterRegistry);
	this.bindingContext = new BindingContext();

	Method method = ReflectionUtils.findMethod(getClass(), "params", (Class<?>[]) null);
	this.cookieParameter = new SynthesizingMethodParameter(method, 0);
	this.cookieStringParameter = new SynthesizingMethodParameter(method, 1);
	this.stringParameter = new SynthesizingMethodParameter(method, 2);
	this.cookieMonoParameter = new SynthesizingMethodParameter(method, 3);
}
 
@Before
@SuppressWarnings("resource")
public void setup() throws Exception {
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
	context.refresh();
	ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
	this.resolver = new RequestHeaderMethodArgumentResolver(context.getBeanFactory(), adapterRegistry);

	ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
	initializer.setConversionService(new DefaultFormattingConversionService());
	this.bindingContext = new BindingContext(initializer);

	Method method = ReflectionUtils.findMethod(getClass(), "params", (Class<?>[]) null);
	this.paramNamedDefaultValueStringHeader = new SynthesizingMethodParameter(method, 0);
	this.paramNamedValueStringArray = new SynthesizingMethodParameter(method, 1);
	this.paramSystemProperty = new SynthesizingMethodParameter(method, 2);
	this.paramResolvedNameWithExpression = new SynthesizingMethodParameter(method, 3);
	this.paramResolvedNameWithPlaceholder = new SynthesizingMethodParameter(method, 4);
	this.paramNamedValueMap = new SynthesizingMethodParameter(method, 5);
	this.paramDate = new SynthesizingMethodParameter(method, 6);
	this.paramInstant = new SynthesizingMethodParameter(method, 7);
	this.paramMono = new SynthesizingMethodParameter(method, 8);
}
 
private void updateBindingContext(BindingContext context, ServerWebExchange exchange) {
	Map<String, Object> model = context.getModel().asMap();
	model.keySet().stream()
			.filter(name -> isBindingCandidate(name, model.get(name)))
			.filter(name -> !model.containsKey(BindingResult.MODEL_KEY_PREFIX + name))
			.forEach(name -> {
				WebExchangeDataBinder binder = context.createDataBinder(exchange, model.get(name), name);
				model.put(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
			});
}
 
@Nullable
@Override
public Object resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext,
		ServerWebExchange exchange) {

	Map<String, MultiValueMap<String, String>> matrixVariables =
			exchange.getAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE);

	if (CollectionUtils.isEmpty(matrixVariables)) {
		return Collections.emptyMap();
	}

	MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
	MatrixVariable annotation = parameter.getParameterAnnotation(MatrixVariable.class);
	Assert.state(annotation != null, "No MatrixVariable annotation");
	String pathVariable = annotation.pathVar();

	if (!pathVariable.equals(ValueConstants.DEFAULT_NONE)) {
		MultiValueMap<String, String> mapForPathVariable = matrixVariables.get(pathVariable);
		if (mapForPathVariable == null) {
			return Collections.emptyMap();
		}
		map.putAll(mapForPathVariable);
	}
	else {
		for (MultiValueMap<String, String> vars : matrixVariables.values()) {
			vars.forEach((name, values) -> {
				for (String value : values) {
					map.add(name, value);
				}
			});
		}
	}

	return (isSingleValueMap(parameter) ? map.toSingleValueMap() : map);
}
 
private void validate(Object target, Object[] validationHints, MethodParameter param,
		BindingContext binding, ServerWebExchange exchange) {

	String name = Conventions.getVariableNameForParameter(param);
	WebExchangeDataBinder binder = binding.createDataBinder(exchange, target, name);
	binder.validate(validationHints);
	if (binder.getBindingResult().hasErrors()) {
		throw new WebExchangeBindException(param, binder.getBindingResult());
	}
}
 
源代码13 项目: spring-analysis-note   文件: ModelInitializer.java
private Mono<Void> handleResult(HandlerResult handlerResult, BindingContext bindingContext) {
	Object value = handlerResult.getReturnValue();
	if (value != null) {
		ResolvableType type = handlerResult.getReturnType();
		ReactiveAdapter adapter = this.adapterRegistry.getAdapter(type.resolve(), value);
		if (isAsyncVoidType(type, adapter)) {
			return Mono.from(adapter.toPublisher(value));
		}
		String name = getAttributeName(handlerResult.getReturnTypeSource());
		bindingContext.getModel().asMap().putIfAbsent(name, value);
	}
	return Mono.empty();
}
 
@Override
public Mono<Object> resolveArgument(
		MethodParameter param, BindingContext bindingContext, ServerWebExchange exchange) {

	RequestBody ann = param.getParameterAnnotation(RequestBody.class);
	Assert.state(ann != null, "No RequestBody annotation");
	return readBody(param, ann.required(), bindingContext, exchange);
}
 
@Nullable
@Override
public Object resolveArgumentValue(
		MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) {

	Assert.isInstanceOf(InitBinderBindingContext.class, bindingContext);
	return ((InitBinderBindingContext) bindingContext).getSessionStatus();
}
 
@Override
public Object resolveArgumentValue(
		MethodParameter methodParameter, BindingContext context, ServerWebExchange exchange) {

	boolean isMultiValueMap = MultiValueMap.class.isAssignableFrom(methodParameter.getParameterType());
	HttpHeaders headers = exchange.getRequest().getHeaders();
	return (isMultiValueMap ? headers : headers.toSingleValueMap());
}
 
@Override
public Mono<Object> resolveArgument(
		MethodParameter parameter, BindingContext context, ServerWebExchange exchange) {

	Object errors = getErrors(parameter, context);
	if (Mono.class.isAssignableFrom(errors.getClass())) {
		return ((Mono<?>) errors).cast(Object.class);
	}
	else if (Errors.class.isAssignableFrom(errors.getClass())) {
		return Mono.just(errors);
	}
	else {
		throw new IllegalStateException("Unexpected Errors/BindingResult type: " + errors.getClass().getName());
	}
}
 
@Test
public void resolveArgument() throws Exception {
	MultiValueMap<String, String> params = getMatrixVariables("cars");
	params.add("colors", "red");
	params.add("colors", "green");
	params.add("colors", "blue");
	params.add("year", "2012");

	MethodParameter param = this.testMethod.annot(matrixAttribute().noName())
			.arg(Map.class, String.class, String.class);

	@SuppressWarnings("unchecked")
	Map<String, String> map =
			(Map<String, String>) this.resolver.resolveArgument(
					param, new BindingContext(), this.exchange).block(Duration.ZERO);

	assertNotNull(map);
	assertEquals("red", map.get("colors"));

	param = this.testMethod
			.annot(matrixAttribute().noPathVar())
			.arg(MultiValueMap.class, String.class, String.class);

	@SuppressWarnings("unchecked")
	MultiValueMap<String, String> multivalueMap =
			(MultiValueMap<String, String>) this.resolver.resolveArgument(
					param, new BindingContext(), this.exchange).block(Duration.ZERO);

	assertEquals(Arrays.asList("red", "green", "blue"), multivalueMap.get("colors"));
}
 
@Test
public void resolveArgument() throws Exception {
	Map<String, String> uriTemplateVars = new HashMap<>();
	uriTemplateVars.put("name1", "value1");
	uriTemplateVars.put("name2", "value2");
	this.exchange.getAttributes().put(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars);

	Mono<Object> mono = this.resolver.resolveArgument(this.paramMap, new BindingContext(), this.exchange);
	Object result = mono.block();

	assertEquals(uriTemplateVars, result);
}
 
InitBinderBindingContext(@Nullable WebBindingInitializer initializer,
		List<SyncInvocableHandlerMethod> binderMethods) {

	super(initializer);
	this.binderMethods = binderMethods;
	this.binderMethodContext = new BindingContext(initializer);
}
 
@Override
public Mono<Object> resolveArgument(
		MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) {

	NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
	MethodParameter nestedParameter = parameter.nestedIfOptional();

	Object resolvedName = resolveStringValue(namedValueInfo.name);
	if (resolvedName == null) {
		return Mono.error(new IllegalArgumentException(
				"Specified name must not resolve to null: [" + namedValueInfo.name + "]"));
	}

	Model model = bindingContext.getModel();

	return resolveName(resolvedName.toString(), nestedParameter, exchange)
			.flatMap(arg -> {
				if ("".equals(arg) && namedValueInfo.defaultValue != null) {
					arg = resolveStringValue(namedValueInfo.defaultValue);
				}
				arg = applyConversion(arg, namedValueInfo, parameter, bindingContext, exchange);
				handleResolvedValue(arg, namedValueInfo.name, parameter, model, exchange);
				return Mono.justOrEmpty(arg);
			})
			.switchIfEmpty(getDefaultValue(
					namedValueInfo, parameter, bindingContext, model, exchange));
}
 
@Override
public Mono<Object> resolveArgument(
		MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) {

	Class<?> entityType = parameter.getParameterType();
	return readBody(parameter.nested(), parameter, false, bindingContext, exchange)
			.map(body -> createEntity(body, entityType, exchange.getRequest()))
			.defaultIfEmpty(createEntity(null, entityType, exchange.getRequest()));
}
 
private Flux<?> decodePartValues(Flux<Part> parts, MethodParameter elementType, BindingContext bindingContext,
		ServerWebExchange exchange, boolean isRequired) {

	return parts.flatMap(part -> {
		ServerHttpRequest partRequest = new PartServerHttpRequest(exchange.getRequest(), part);
		ServerWebExchange partExchange = exchange.mutate().request(partRequest).build();
		if (logger.isDebugEnabled()) {
			logger.debug(exchange.getLogPrefix() + "Decoding part '" + part.name() + "'");
		}
		return readBody(elementType, isRequired, bindingContext, partExchange);
	});
}
 
@Override
public Mono<Object> resolveArgument(
		MethodParameter parameter, BindingContext context, ServerWebExchange exchange) {

	Mono<Principal> principal = exchange.getPrincipal();
	ReactiveAdapter adapter = getAdapterRegistry().getAdapter(parameter.getParameterType());
	return (adapter != null ? Mono.just(adapter.fromPublisher(principal)) : Mono.from(principal));
}
 
@SuppressWarnings("unchecked")
private <T> T resolveValueWithEmptyBody(MethodParameter param) {
	ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.post("/path"));
	Mono<Object> result = this.resolver.resolveArgument(param, new BindingContext(), exchange);
	Object value = result.block(Duration.ofSeconds(5));

	if (value != null) {
		assertTrue("Unexpected parameter type: " + value,
				param.getParameterType().isAssignableFrom(value.getClass()));
	}

	//no inspection unchecked
	return (T) value;
}
 
@Test
public void resolveArgumentNoUriVars() throws Exception {
	Mono<Object> mono = this.resolver.resolveArgument(this.paramMap, new BindingContext(), this.exchange);
	Object result = mono.block();

	assertEquals(Collections.emptyMap(), result);
}
 
@Override
public Object resolveArgumentValue(
		MethodParameter methodParameter, BindingContext context, ServerWebExchange exchange) {

	String name = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
	return exchange.getAttributeOrDefault(name, Collections.emptyMap());
}
 
@Test
public void resolveArgumentWrappedAsOptional() throws Exception {
	Map<String, String> uriTemplateVars = new HashMap<>();
	uriTemplateVars.put("name", "value");
	this.exchange.getAttributes().put(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVars);

	ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
	initializer.setConversionService(new DefaultFormattingConversionService());
	BindingContext bindingContext = new BindingContext(initializer);

	Mono<Object> mono = this.resolver.resolveArgument(this.paramOptional, bindingContext, this.exchange);
	Object result = mono.block();
	assertEquals(Optional.of("value"), result);
}
 
@Override
public Mono<Object> resolveArgument(
		MethodParameter parameter, BindingContext bindingContext, ServerWebExchange exchange) {

	// Flip the default implementation from SyncHandlerMethodArgumentResolver:
	// instead of delegating to (sync) resolveArgumentValue,
	// call (async) super.resolveArgument shared with non-blocking resolvers;
	// actual resolution below still sync...

	return super.resolveArgument(parameter, bindingContext, exchange);
}
 
@Nullable
@Override
public Object resolveArgumentValue(MethodParameter parameter, BindingContext bindingContext,
		ServerWebExchange exchange) {

	Map<String, MultiValueMap<String, String>> matrixVariables =
			exchange.getAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE);

	if (CollectionUtils.isEmpty(matrixVariables)) {
		return Collections.emptyMap();
	}

	MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
	MatrixVariable annotation = parameter.getParameterAnnotation(MatrixVariable.class);
	Assert.state(annotation != null, "No MatrixVariable annotation");
	String pathVariable = annotation.pathVar();

	if (!pathVariable.equals(ValueConstants.DEFAULT_NONE)) {
		MultiValueMap<String, String> mapForPathVariable = matrixVariables.get(pathVariable);
		if (mapForPathVariable == null) {
			return Collections.emptyMap();
		}
		map.putAll(mapForPathVariable);
	}
	else {
		for (MultiValueMap<String, String> vars : matrixVariables.values()) {
			vars.forEach((name, values) -> {
				for (String value : values) {
					map.add(name, value);
				}
			});
		}
	}

	return (isSingleValueMap(parameter) ? map.toSingleValueMap() : map);
}