下面列出了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());
}
}
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);
}