Spring MVC 自定义格式化程序在测试中工作但在浏览器中失败
Spring MVC custom Formatter works in Test but fails in Browser
我有一个 控制器:(根据 Spring WebMVC @ModelAttribute parameter-style)
@GetMapping("/time/{date}")
@ResponseStatus(OK)
public LocalDate getDate(
@ModelAttribute("date") LocalDate date
) {
return date;
}
LocalDateFormatter 从字符串 "now"、[=77= 编码 LocalDate
s ] 和典型的 "yyyy-MM-dd" 格式的字符串,并且解码日期可以追溯到字符串
public class LocalDateFormatter implements Formatter<LocalDate> {}
我已经通过 Spring 测试 测试了 这个控制器。测试 通过.
我设置了一个转换服务并用它模拟了一个 MVC:
var conversion = new DefaultFormattingConversionService();
conversion.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
mockMvc = MockMvcBuilders
.standaloneSetup(TimeController.class)
.setConversionService(conversionRegistry)
.build();
测试已参数化,如下所示:
@ParameterizedTest
@MethodSource("args")
void getDate(String rawDate, boolean shouldConvert) throws Exception {
var getTime = mockMvc.perform(get("/time/" + rawDate));
if (shouldConvert) {
// Date is successfully parsed and some JSON is returned
getTime.andExpect(content().contentType(APPLICATION_JSON_UTF8));
} else {
// Unsupported rawDate
getTime.andExpect(status().is(400));
}
}
参数如下:
private static Stream<Arguments> args() {
// true if string should be parsed
return Stream.of(
Arguments.of("now", true),
Arguments.of("today", true),
Arguments.of("thisOneShouldNotWork", false),
Arguments.of("2014-11-27", true)
);
}
如我所说,测试通过。
但是当从 浏览器 启动时,任何请求都会收到 400 错误。
我如何尝试 将转换集成到 Spring MVC(none 有效):
覆盖WebMvcConfigurer
的方法:
public class ServletConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new LocalDateFormatter());
// ALSO TRIED
registry.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
}
}
注册一个FormattingConversionService
@Bean
public FormattingConversionService conversionService() {
var service = new FormattingConversionService();
service.addFormatter(new LocalDateFormatter());
return service;
}
谁能告诉我怎么了?
P.S. 我知道这不是处理日期的最佳方式,但是因为它在 Spring 中提到了这个应该可以,我想试试。
为 spring 引导定义此 bean:
@Bean
public Formatter<LocalDate> localDateFormatter() {
return new Formatter<LocalDate>() {
@Override
public LocalDate parse(String text, Locale locale) throws ParseException {
if ("now".equals(text))
return LocalDate.now();
return LocalDate.parse(text, DateTimeFormatter.ISO_DATE);
}
@Override
public String print(LocalDate object, Locale locale) {
return DateTimeFormatter.ISO_DATE.format(object);
}
};
}
如果你使用 Spring MVC 定义如下:
@Configuration
@ComponentScan
@EnableWebMvc
public class ServletConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new Formatter<LocalDate>() {
@Override
public LocalDate parse(String text, Locale locale) throws ParseException {
if ("now".equals(text))
return LocalDate.now();
return LocalDate.parse(text, DateTimeFormatter.ISO_DATE);
}
@Override
public String print(LocalDate object, Locale locale) {
return DateTimeFormatter.ISO_DATE.format(object);
}
});
}
}
不要忘记实现 today
函数作为参数。
我有一个 控制器:(根据 Spring WebMVC @ModelAttribute parameter-style)
@GetMapping("/time/{date}")
@ResponseStatus(OK)
public LocalDate getDate(
@ModelAttribute("date") LocalDate date
) {
return date;
}
LocalDateFormatter 从字符串 "now"、[=77= 编码 LocalDate
s ] 和典型的 "yyyy-MM-dd" 格式的字符串,并且解码日期可以追溯到字符串
public class LocalDateFormatter implements Formatter<LocalDate> {}
我已经通过 Spring 测试 测试了 这个控制器。测试 通过.
我设置了一个转换服务并用它模拟了一个 MVC:
var conversion = new DefaultFormattingConversionService();
conversion.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter());
mockMvc = MockMvcBuilders
.standaloneSetup(TimeController.class)
.setConversionService(conversionRegistry)
.build();
测试已参数化,如下所示:
@ParameterizedTest
@MethodSource("args")
void getDate(String rawDate, boolean shouldConvert) throws Exception {
var getTime = mockMvc.perform(get("/time/" + rawDate));
if (shouldConvert) {
// Date is successfully parsed and some JSON is returned
getTime.andExpect(content().contentType(APPLICATION_JSON_UTF8));
} else {
// Unsupported rawDate
getTime.andExpect(status().is(400));
}
}
参数如下:
private static Stream<Arguments> args() {
// true if string should be parsed
return Stream.of(
Arguments.of("now", true),
Arguments.of("today", true),
Arguments.of("thisOneShouldNotWork", false),
Arguments.of("2014-11-27", true)
);
}
如我所说,测试通过。
但是当从 浏览器 启动时,任何请求都会收到 400 错误。
我如何尝试 将转换集成到 Spring MVC(none 有效):
覆盖
WebMvcConfigurer
的方法:public class ServletConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addFormatter(new LocalDateFormatter()); // ALSO TRIED registry.addFormatterForFieldType(LocalDate.class, new LocalDateFormatter()); } }
注册一个
FormattingConversionService
@Bean public FormattingConversionService conversionService() { var service = new FormattingConversionService(); service.addFormatter(new LocalDateFormatter()); return service; }
谁能告诉我怎么了?
P.S. 我知道这不是处理日期的最佳方式,但是因为它在 Spring 中提到了这个应该可以,我想试试。
为 spring 引导定义此 bean:
@Bean
public Formatter<LocalDate> localDateFormatter() {
return new Formatter<LocalDate>() {
@Override
public LocalDate parse(String text, Locale locale) throws ParseException {
if ("now".equals(text))
return LocalDate.now();
return LocalDate.parse(text, DateTimeFormatter.ISO_DATE);
}
@Override
public String print(LocalDate object, Locale locale) {
return DateTimeFormatter.ISO_DATE.format(object);
}
};
}
如果你使用 Spring MVC 定义如下:
@Configuration
@ComponentScan
@EnableWebMvc
public class ServletConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new Formatter<LocalDate>() {
@Override
public LocalDate parse(String text, Locale locale) throws ParseException {
if ("now".equals(text))
return LocalDate.now();
return LocalDate.parse(text, DateTimeFormatter.ISO_DATE);
}
@Override
public String print(LocalDate object, Locale locale) {
return DateTimeFormatter.ISO_DATE.format(object);
}
});
}
}
不要忘记实现 today
函数作为参数。