parent
ae003e89c1
commit
e59dcedfee
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.web.reactive.result.view;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -38,11 +39,14 @@ import org.springframework.http.MediaType;
|
|||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.WebExchangeDataBinder;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.reactive.HandlerResult;
|
||||
import org.springframework.web.reactive.HandlerResultHandler;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
|
||||
import org.springframework.web.reactive.result.AbstractHandlerResultHandler;
|
||||
import org.springframework.web.reactive.result.method.BindingContext;
|
||||
import org.springframework.web.server.NotAcceptableStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.util.HttpRequestPathHelper;
|
||||
|
@ -241,6 +245,7 @@ public class ViewResolutionResultHandler extends AbstractHandlerResultHandler
|
|||
}
|
||||
|
||||
return resolveAsyncAttributes(model.asMap())
|
||||
.doOnSuccess(aVoid -> addBindingResult(result, exchange))
|
||||
.then(viewsMono)
|
||||
.then(views -> render(views, model.asMap(), exchange));
|
||||
});
|
||||
|
@ -322,6 +327,24 @@ public class ViewResolutionResultHandler extends AbstractHandlerResultHandler
|
|||
.then();
|
||||
}
|
||||
|
||||
private void addBindingResult(HandlerResult result, ServerWebExchange exchange) {
|
||||
BindingContext context = result.getBindingContext();
|
||||
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());
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isBindingCandidate(String name, Object value) {
|
||||
return !name.startsWith(BindingResult.MODEL_KEY_PREFIX) && value != null &&
|
||||
!value.getClass().isArray() && !(value instanceof Collection) &&
|
||||
!(value instanceof Map) && !BeanUtils.isSimpleValueType(value.getClass());
|
||||
}
|
||||
|
||||
private Mono<? extends Void> render(List<View> views, Map<String, Object> model,
|
||||
ServerWebExchange exchange) {
|
||||
|
||||
|
|
|
@ -166,7 +166,12 @@ public class ViewResolutionResultHandlerTests {
|
|||
|
||||
returnType = forClass(TestBean.class);
|
||||
returnValue = new TestBean("Joe");
|
||||
String responseBody = "account: {id=123, testBean=TestBean[name=Joe]}";
|
||||
String responseBody = "account: {" +
|
||||
"id=123, " +
|
||||
"org.springframework.validation.BindingResult.testBean=" +
|
||||
"org.springframework.validation.BeanPropertyBindingResult: 0 errors, " +
|
||||
"testBean=TestBean[name=Joe]" +
|
||||
"}";
|
||||
testHandle("/account", returnType, returnValue, responseBody, resolver);
|
||||
|
||||
testHandle("/account", resolvableMethod().annotated(ModelAttribute.class),
|
||||
|
@ -239,7 +244,11 @@ public class ViewResolutionResultHandlerTests {
|
|||
.block(Duration.ofSeconds(5));
|
||||
|
||||
assertEquals(APPLICATION_JSON, this.response.getHeaders().getContentType());
|
||||
assertResponseBody("jsonView: {testBean=TestBean[name=Joe]}");
|
||||
assertResponseBody("jsonView: {" +
|
||||
"org.springframework.validation.BindingResult.testBean=" +
|
||||
"org.springframework.validation.BeanPropertyBindingResult: 0 errors, " +
|
||||
"testBean=TestBean[name=Joe]" +
|
||||
"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -272,7 +281,14 @@ public class ViewResolutionResultHandlerTests {
|
|||
|
||||
this.request.setUri("/account");
|
||||
handler.handleResult(this.exchange, result).blockMillis(5000);
|
||||
assertResponseBody("account: {bean1=TestBean[name=Bean1], bean2=TestBean[name=Bean2]}");
|
||||
assertResponseBody("account: {" +
|
||||
"bean1=TestBean[name=Bean1], " +
|
||||
"bean2=TestBean[name=Bean2], " +
|
||||
"org.springframework.validation.BindingResult.bean1=" +
|
||||
"org.springframework.validation.BeanPropertyBindingResult: 0 errors, " +
|
||||
"org.springframework.validation.BindingResult.bean2=" +
|
||||
"org.springframework.validation.BeanPropertyBindingResult: 0 errors" +
|
||||
"}");
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue