mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Set embeddedValueResolver on WebConversionService
Closes gh-8923
This commit is contained in:
committed by
Moritz Halbritter
parent
d04cb90d19
commit
a04b65ea74
+18
-1
@@ -31,6 +31,7 @@ import org.springframework.format.number.money.Jsr354NumberFormatAnnotationForma
|
||||
import org.springframework.format.number.money.MonetaryAmountFormatter;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.format.support.FormattingConversionService} dedicated to web
|
||||
@@ -53,7 +54,23 @@ public class WebConversionService extends DefaultFormattingConversionService {
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public WebConversionService(DateTimeFormatters dateTimeFormatters) {
|
||||
super(false);
|
||||
this(null, dateTimeFormatters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new WebConversionService that configures formatters with the provided
|
||||
* date, time, and date-time formats, or registers the default if no custom format is
|
||||
* provided. The given {@code embeddedValueResolver} is used to resolve embedded
|
||||
* values such as property placeholders in
|
||||
* {@link org.springframework.format.annotation.DateTimeFormat#pattern()} patterns.
|
||||
* @param embeddedValueResolver the embedded value resolver to use, or {@code null}
|
||||
* @param dateTimeFormatters the formatters to use for date, time, and date-time
|
||||
* formatting
|
||||
* @since 4.1.0
|
||||
*/
|
||||
public WebConversionService(@Nullable StringValueResolver embeddedValueResolver,
|
||||
DateTimeFormatters dateTimeFormatters) {
|
||||
super(embeddedValueResolver, false);
|
||||
if (dateTimeFormatters.isCustomized()) {
|
||||
addFormatters(dateTimeFormatters);
|
||||
}
|
||||
|
||||
+21
@@ -29,8 +29,12 @@ import java.time.format.FormatStyle;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
@@ -178,10 +182,27 @@ class WebConversionServiceTests {
|
||||
assertThat(calendar.get(Calendar.DAY_OF_MONTH)).isOne();
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedValueResolverIsAppliedToAnnotationPattern() throws Exception {
|
||||
WebConversionService conversionService = new WebConversionService(
|
||||
(value) -> value.replace("${my.date.format}", "yyyy-MM-dd"), new DateTimeFormatters());
|
||||
TypeDescriptor dateType = new TypeDescriptor(FormattedDate.class.getDeclaredField("date"));
|
||||
Date date = Date.from(ZonedDateTime.of(2000, 1, 2, 3, 4, 5, 6, ZoneId.of("UTC")).toInstant());
|
||||
assertThat(conversionService.convert(date, dateType, TypeDescriptor.valueOf(String.class)))
|
||||
.isEqualTo("2000-01-02");
|
||||
}
|
||||
|
||||
private void customDateFormat(Object input) {
|
||||
WebConversionService conversionService = new WebConversionService(
|
||||
new DateTimeFormatters().dateFormat("dd*MM*yyyy"));
|
||||
assertThat(conversionService.convert(input, String.class)).isEqualTo("01*01*2018");
|
||||
}
|
||||
|
||||
static class FormattedDate {
|
||||
|
||||
@DateTimeFormat(pattern = "${my.date.format}")
|
||||
@Nullable Date date;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-2
@@ -59,6 +59,7 @@ import org.springframework.boot.webflux.autoconfigure.WebFluxProperties.Apiversi
|
||||
import org.springframework.boot.webflux.autoconfigure.WebFluxProperties.Format;
|
||||
import org.springframework.boot.webflux.filter.OrderedHiddenHttpMethodFilter;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@@ -73,6 +74,7 @@ import org.springframework.http.CacheControl;
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.accept.ApiVersionParser;
|
||||
import org.springframework.web.filter.reactive.HiddenHttpMethodFilter;
|
||||
@@ -312,7 +314,8 @@ public final class WebFluxAutoConfiguration {
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties({ WebProperties.class, ServerProperties.class })
|
||||
@ImportRuntimeHints(WebFluxValidatorRuntimeHints.class)
|
||||
static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration {
|
||||
static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration
|
||||
implements EmbeddedValueResolverAware {
|
||||
|
||||
private final WebFluxProperties webFluxProperties;
|
||||
|
||||
@@ -322,6 +325,8 @@ public final class WebFluxAutoConfiguration {
|
||||
|
||||
private final @Nullable WebFluxRegistrations webFluxRegistrations;
|
||||
|
||||
private @Nullable StringValueResolver embeddedValueResolver;
|
||||
|
||||
EnableWebFluxConfiguration(WebFluxProperties webFluxProperties, WebProperties webProperties,
|
||||
ServerProperties serverProperties, ObjectProvider<WebFluxRegistrations> webFluxRegistrations) {
|
||||
this.webFluxProperties = webFluxProperties;
|
||||
@@ -334,7 +339,7 @@ public final class WebFluxAutoConfiguration {
|
||||
@Override
|
||||
public FormattingConversionService webFluxConversionService() {
|
||||
Format format = this.webFluxProperties.getFormat();
|
||||
WebConversionService conversionService = new WebConversionService(
|
||||
WebConversionService conversionService = new WebConversionService(this.embeddedValueResolver,
|
||||
new DateTimeFormatters().dateFormat(format.getDate())
|
||||
.timeFormat(format.getTime())
|
||||
.dateTimeFormat(format.getDateTime()));
|
||||
@@ -342,6 +347,11 @@ public final class WebFluxAutoConfiguration {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public Validator webFluxValidator() {
|
||||
|
||||
+20
@@ -74,10 +74,12 @@ import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
@@ -340,6 +342,17 @@ class WebFluxAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedValueResolverIsAppliedToConversionService() throws Exception {
|
||||
this.contextRunner.withPropertyValues("my.date.format=yyyy-MM-dd").run((context) -> {
|
||||
FormattingConversionService conversionService = context.getBean(FormattingConversionService.class);
|
||||
TypeDescriptor dateType = new TypeDescriptor(FormattedDate.class.getDeclaredField("date"));
|
||||
Date date = Date.from(ZonedDateTime.of(2000, 1, 2, 3, 4, 5, 6, ZoneId.of("UTC")).toInstant());
|
||||
assertThat(conversionService.convert(date, dateType, TypeDescriptor.valueOf(String.class)))
|
||||
.isEqualTo("2000-01-02");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void validatorWhenNoValidatorShouldUseDefault() {
|
||||
this.contextRunner.run((context) -> {
|
||||
@@ -1333,4 +1346,11 @@ class WebFluxAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
static class FormattedDate {
|
||||
|
||||
@DateTimeFormat(pattern = "${my.date.format}")
|
||||
@Nullable Date date;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-2
@@ -67,6 +67,7 @@ import org.springframework.boot.webmvc.autoconfigure.WebMvcProperties.Apiversion
|
||||
import org.springframework.boot.webmvc.autoconfigure.WebMvcProperties.Apiversion.Use;
|
||||
import org.springframework.boot.webmvc.autoconfigure.WebMvcProperties.Format;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -87,6 +88,7 @@ import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
import org.springframework.validation.DefaultMessageCodesResolver;
|
||||
import org.springframework.validation.MessageCodesResolver;
|
||||
import org.springframework.validation.Validator;
|
||||
@@ -438,7 +440,8 @@ public final class WebMvcAutoConfiguration {
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(WebProperties.class)
|
||||
@ImportRuntimeHints(MvcValidatorRuntimeHints.class)
|
||||
static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
|
||||
static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration
|
||||
implements ResourceLoaderAware, EmbeddedValueResolverAware {
|
||||
|
||||
private final Resources resourceProperties;
|
||||
|
||||
@@ -450,6 +453,8 @@ public final class WebMvcAutoConfiguration {
|
||||
|
||||
private final @Nullable WebMvcRegistrations mvcRegistrations;
|
||||
|
||||
private @Nullable StringValueResolver embeddedValueResolver;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@@ -566,7 +571,7 @@ public final class WebMvcAutoConfiguration {
|
||||
@Override
|
||||
public FormattingConversionService mvcConversionService() {
|
||||
Format format = this.mvcProperties.getFormat();
|
||||
WebConversionService conversionService = new WebConversionService(
|
||||
WebConversionService conversionService = new WebConversionService(this.embeddedValueResolver,
|
||||
new DateTimeFormatters().dateFormat(format.getDate())
|
||||
.timeFormat(format.getTime())
|
||||
.dateTimeFormat(format.getDateTime()));
|
||||
@@ -574,6 +579,11 @@ public final class WebMvcAutoConfiguration {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public Validator mvcValidator() {
|
||||
|
||||
+20
@@ -78,11 +78,13 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -509,6 +511,17 @@ class WebMvcAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void embeddedValueResolverIsAppliedToConversionService() throws Exception {
|
||||
this.contextRunner.withPropertyValues("my.date.format=yyyy-MM-dd").run((context) -> {
|
||||
FormattingConversionService conversionService = context.getBean(FormattingConversionService.class);
|
||||
TypeDescriptor dateType = new TypeDescriptor(FormattedDate.class.getDeclaredField("date"));
|
||||
Date date = Date.from(ZonedDateTime.of(2000, 1, 2, 3, 4, 5, 6, ZoneId.of("UTC")).toInstant());
|
||||
assertThat(conversionService.convert(date, dateType, TypeDescriptor.valueOf(String.class)))
|
||||
.isEqualTo("2000-01-02");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void noMessageCodesResolver() {
|
||||
this.contextRunner.run(
|
||||
@@ -1756,4 +1769,11 @@ class WebMvcAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
static class FormattedDate {
|
||||
|
||||
@DateTimeFormat(pattern = "${my.date.format}")
|
||||
@Nullable Date date;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user