Update contribution

Closes gh-33220
This commit is contained in:
rstoyanchev
2024-07-30 13:15:21 +03:00
parent 5e9308e0cb
commit f967f6f9f0
3 changed files with 67 additions and 52 deletions

View File

@@ -129,7 +129,7 @@ public abstract class AbstractNamedValueArgumentResolver implements HttpServiceA
*/
@Nullable
protected NamedValueInfo createNamedValueInfo(
MethodParameter parameter, HttpRequestValues.Metadata requestValues) {
MethodParameter parameter, HttpRequestValues.Metadata metadata) {
return createNamedValueInfo(parameter);
}
@@ -246,6 +246,8 @@ public abstract class AbstractNamedValueArgumentResolver implements HttpServiceA
* @param required whether it is marked as required
* @param defaultValue fallback value, possibly {@link ValueConstants#DEFAULT_NONE}
* @param label how it should appear in error messages, e.g. "path variable", "request header"
* @param multiValued whether this argument resolver supports sending multiple values;
* if not, then multiple values are formatted as a String value
*/
public NamedValueInfo(
String name, boolean required, @Nullable String defaultValue, String label, boolean multiValued) {

View File

@@ -55,41 +55,72 @@ import org.springframework.web.bind.annotation.RequestParam;
*/
public class RequestParamArgumentResolver extends AbstractNamedValueArgumentResolver {
private boolean formatAsSingleValue = true;
private boolean favorSingleValue;
public RequestParamArgumentResolver(ConversionService conversionService) {
super(conversionService);
}
public RequestParamArgumentResolver(ConversionService conversionService, boolean formatAsSingleValue) {
super(conversionService);
this.formatAsSingleValue = formatAsSingleValue;
/**
* Whether to format multiple values (e.g. collection, array) as a single
* String value through the configured {@link ConversionService} unless the
* content type is form data, or it is a multipart request.
* <p>By default, this is {@code false} in which case formatting is not applied,
* and a separate parameter with the same name is created for each value.
* @since 6.2
*/
public void setFavorSingleValue(boolean favorSingleValue) {
this.favorSingleValue = favorSingleValue;
}
/**
* Return the setting for {@link #setFavorSingleValue favorSingleValue}.
* @since 6.2
*/
public boolean isFavorSingleValue() {
return this.favorSingleValue;
}
@Override
@Nullable
protected NamedValueInfo createNamedValueInfo(MethodParameter parameter, HttpRequestValues.Metadata requestValues) {
MediaType contentType = requestValues.getContentType();
if (contentType != null && isMultiValueFormContentType(contentType)) {
this.formatAsSingleValue = true;
}
return createNamedValueInfo(parameter);
}
@Override
@Nullable
protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
protected NamedValueInfo createNamedValueInfo(MethodParameter parameter, HttpRequestValues.Metadata metadata) {
RequestParam annot = parameter.getParameterAnnotation(RequestParam.class);
if (annot == null) {
return null;
}
return new NamedValueInfo(
annot.name(), annot.required(), annot.defaultValue(), "request parameter",
supportsMultipleValues(parameter, metadata));
}
return (annot == null ? null :
new NamedValueInfo(annot.name(), annot.required(), annot.defaultValue(),
"request parameter", this.formatAsSingleValue));
@Override
protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
// Shouldn't be called since we override createNamedValueInfo with HttpRequestValues.Metadata
throw new UnsupportedOperationException();
}
/**
* Determine whether the resolver should send multi-value request parameters
* as individual values. If not, they are formatted to a single String value.
* The default implementation uses {@link #isFavorSingleValue()} to decide
* unless the content type is form data, or it is a multipart request.
* @since 6.2
*/
protected boolean supportsMultipleValues(MethodParameter parameter, HttpRequestValues.Metadata metadata) {
return (!isFavorSingleValue() || isFormOrMultipartContent(metadata));
}
/**
* Whether the content type is form data, or it is a multipart request.
* @since 6.2
*/
protected boolean isFormOrMultipartContent(HttpRequestValues.Metadata metadata) {
MediaType mediaType = metadata.getContentType();
return (mediaType != null && (mediaType.getType().equals("multipart") ||
mediaType.isCompatibleWith(MediaType.APPLICATION_FORM_URLENCODED)));
}
@Override
@@ -99,17 +130,4 @@ public class RequestParamArgumentResolver extends AbstractNamedValueArgumentReso
requestValues.addRequestParameter(name, (String) value);
}
protected boolean isFormatAsSingleValue() {
return this.formatAsSingleValue;
}
protected void setFormatAsSingleValue(boolean formatAsSingleValue) {
this.formatAsSingleValue = formatAsSingleValue;
}
protected boolean isMultiValueFormContentType(MediaType contentType) {
return contentType.equals(MediaType.APPLICATION_FORM_URLENCODED)
|| contentType.getType().equals("multipart");
}
}