Support constructing target object in DataBinder

See gh-26721
This commit is contained in:
rstoyanchev
2023-06-22 20:36:28 +01:00
parent 40bf923d7d
commit ea398d7b7e
11 changed files with 553 additions and 282 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ import jakarta.servlet.ServletRequest;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.servlet.HandlerMapping;
/**
@@ -67,14 +68,17 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
}
@Override
protected ServletRequestValueResolver createValueResolver(ServletRequest request) {
return new ExtendedServletRequestValueResolver(request, this);
}
/**
* Merge URI variables into the property values to use for data binding.
*/
@Override
protected void addBindValues(MutablePropertyValues mpvs, ServletRequest request) {
String attr = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
@SuppressWarnings("unchecked")
Map<String, String> uriVars = (Map<String, String>) request.getAttribute(attr);
Map<String, String> uriVars = getUriVars(request);
if (uriVars != null) {
uriVars.forEach((name, value) -> {
if (mpvs.contains(name)) {
@@ -89,4 +93,34 @@ public class ExtendedServletRequestDataBinder extends ServletRequestDataBinder {
}
}
@SuppressWarnings("unchecked")
@Nullable
private static Map<String, String> getUriVars(ServletRequest request) {
String attr = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
return (Map<String, String>) request.getAttribute(attr);
}
/**
* Resolver of values that looks up URI path variables.
*/
private static class ExtendedServletRequestValueResolver extends ServletRequestValueResolver {
ExtendedServletRequestValueResolver(ServletRequest request, WebDataBinder dataBinder) {
super(request, dataBinder);
}
@Override
protected Object getRequestParameter(String name, Class<?> type) {
Object value = super.getRequestParameter(name, type);
if (value == null) {
Map<String, String> uriVars = getUriVars(getRequest());
if (uriVars != null) {
value = uriVars.get(name);
}
}
return value;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -146,9 +146,18 @@ public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodPr
}
/**
* This implementation downcasts {@link WebDataBinder} to
* {@link ServletRequestDataBinder} before binding.
* @see ServletRequestDataBinderFactory
* Downcast to {@link ServletRequestDataBinder} to invoke {@code constructTarget(ServletRequest)}.
*/
@Override
protected void constructAttribute(WebDataBinder binder, NativeWebRequest request) {
ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class);
Assert.state(servletRequest != null, "No ServletRequest");
ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
servletBinder.construct(servletRequest);
}
/**
* Downcast to {@link ServletRequestDataBinder} to invoke {@code bind(ServletRequest)}.
*/
@Override
protected void bindRequestParameters(WebDataBinder binder, NativeWebRequest request) {
@@ -158,23 +167,4 @@ public class ServletModelAttributeMethodProcessor extends ModelAttributeMethodPr
servletBinder.bind(servletRequest);
}
@Override
@Nullable
public Object resolveConstructorArgument(String paramName, Class<?> paramType, NativeWebRequest request)
throws Exception {
Object value = super.resolveConstructorArgument(paramName, paramType, request);
if (value != null) {
return value;
}
ServletRequest servletRequest = request.getNativeRequest(ServletRequest.class);
if (servletRequest != null) {
String attr = HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE;
@SuppressWarnings("unchecked")
Map<String, String> uriVars = (Map<String, String>) servletRequest.getAttribute(attr);
return uriVars.get(paramName);
}
return null;
}
}