问题描述
我有一个 spring-boot 应用程序,它暴露了一个 Rest API.此 API 接受枚举列表 batchStatus
作为查询参数.此 batchStatus
用于根据状态过滤所有批次.
I have a spring-boot application which is exposing a Rest API. This API accepts a list of enums batchStatus
as query parameter. This batchStatus
is to be used to filter all the batches based on their status.
尝试调用这个rest api时,我收到以下错误
When trying to invoke this rest api, I'm getting the following error
{
"timestamp": 1552587376808,
"status": 400,
"error": "Bad Request",
"message": "Failed to convert value of type 'java.lang.String[]' to required type 'java.util.List'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@io.swagger.annotations.ApiParam @javax.validation.Valid @org.springframework.web.bind.annotation.RequestParam com.netshell.test.spring.conversion.rest.api.model.BatchStatus] for value 'active'; nested exception is java.lang.IllegalArgumentException: No enum constant com.netshell.test.spring.conversion.rest.api.model.BatchStatus.active",
"path": "/batch/status"
}
Spring 在 BatchStatus 中寻找 active 而不是 ACTIVE.
Spring is looking for active in BatchStatus instead of ACTIVE.
深入研究 spring ConversionService 我发现了两个转换器
1. StringToEnumConverterFactory(来自spring-core)
2. StringToEnumIgnoringCaseConverterFactory(来自spring-boot)
Looking deep into the spring ConversionService I've discovered two converters
1. StringToEnumConverterFactory (from spring-core)
2. StringToEnumIgnoringCaseConverterFactory (from spring-boot)
spring-boot 中是否有强制使用第二个转换器的机制?
Is there any mechanism in spring-boot to force use of second converter?
进一步调试显示两个转换器都注册了ConversionService,但是有多个conversionService实例 每个都有不同数量的转换器.这种情况下spring如何选择使用哪个conversionService?
Further debugging showed that both the converters are registered with ConversionService, however there are multiple instances of conversionService each with different number of converters. In this case how does spring select which conversionService to use?
Enum BatchStatus
创建如下
public enum BatchStatus {
ACTIVE("active"),
FAILED("failed"),
HOLD("hold");
private String value;
BatchStatus(String value) {
this.value = value;
}
@Override
@JsonValue
public String toString() {
return String.valueOf(value);
}
@JsonCreator
public static BatchStatus fromValue(String text) {
for (BatchStatus b : BatchStatus.values()) {
if (String.valueOf(b.value).equals(text)) {
return b;
}
}
return null;
}
}
推荐答案
查看 Spring 项目的 issue tracker 可以找到 this 问题,基本上要求将 StringToEnumIgnoringCaseConverterFactory
类公开.
然而,它似乎不会很快发生,因为 this 是仍在进行中.
Looking at the issue tracker of the Spring project you can find this issue, which basically asks for the StringToEnumIgnoringCaseConverterFactory
class to be made public.
However it seems it won't happen anytime soon, as this is still in progress.
您可以尝试通过 WebMvcConfigurer#addFormatters
@Configuration
class CustomWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addFormatters(final FormatterRegistry registry) {
ApplicationConversionService.configure(registry);
}
}
ApplicationConversionService#configure
将通过调用 addApplicationConverters
方法为您注册 StringToEnumIgnoringCaseConverterFactory
ApplicationConversionService#configure
will register StringToEnumIgnoringCaseConverterFactory
for you, by calling the addApplicationConverters
method
/** Spring Framework code */
public static void addApplicationConverters(ConverterRegistry registry) {
...
registry.addConverterFactory(new StringToEnumIgnoringCaseConverterFactory());
}
顺便说一句,这是对 StringToEnumIgnoringCaseConverterFactory
的唯一引用,所以这是您唯一的希望;)(不要使用Reflection
!忍住冲动)
And btw, that's the only reference to StringToEnumIgnoringCaseConverterFactory
, so it's your only hope ; ) (don't use Reflection
! Resist the urge)
这篇关于Spring Boot 转换枚举忽略大小写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!