在@BeanParam 中使用枚举
Using an Enum in @BeanParam
我正在使用这样的@BeanParam:
@GET
public Response listAllPaged(@BeanParam PagedRequest pagedRequest) {
// Do stuff...
}
bean 本身:
public class PagedRequest {
@QueryParam("sortOrder")
@DefaultValue("0")
public int sortOrder;
}
现在我想将 sortOrder 的类型更改为以下枚举:
public enum SortOrder {
ASC("asc"),
DESC("desc");
public final String sortOrder;
SortOrder(String sortOrder) {
this.sortOrder = sortOrder;
}
}
但是一旦我这样做:
public class PagedRequest {
@QueryParam("sortOrder")
@DefaultValue("asc")
public SortOrder sortOrder;
}
我的 REST 端点无法再匹配签名和 returns 404。这是为什么?我认为接受单个字符串的构造函数的存在应该允许 JAX-RS 进行转换。
我做错了什么?
更新
我设法让它像这样工作,但它并没有真正回答我最初的问题...
public enum SortOrder {
ASC,
DESC;
public static SortOrder fromString(String param) {
String toUpper = param.toUpperCase();
try {
return valueOf(toUpper);
} catch (Exception e) {
return null;
}
}
}
Enum.valueOf(String)
方法用于解析值。由于您的 SorterOrder
枚举是大写的,因此您需要以大写形式发送参数。
如果您只想传递小写的值,您可以将枚举名称更改为小写,例如SortOrder.asc
.
如果您不知道或不想关心参数发送的大小写,您可以使用 ParamConverter
.
public class SortOrderParamConverter implements ParamConverter<SortOrder> {
@Override
public SortOrder fromString(final String value) {
if (value != null) {
return SortOrder.valueOf(value.toUpperCase(Locale.ROOT));
}
return SortOrder.ASC;
}
@Override
public String toString(final SortOrder value) {
return value.name();
}
}
如果您想要更通用的方法,您可以创建一个 ParamConverter
或所有枚举。
@Provider
public class EnumParamConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(final Class<T> rawType, final Type genericType,
final Annotation[] annotations) {
if (!rawType.isEnum()) {
return null;
}
final Enum<?>[] constants = (Enum<?>[]) rawType.getEnumConstants();
return new ParamConverter<T>() {
@Override
@SuppressWarnings("unchecked")
public T fromString(final String value) {
if (value == null || value.isEmpty()) {
return null;
}
for (Enum<?> e : constants) {
if (e.name().equalsIgnoreCase(value)) {
return (T) e;
}
}
// No match, check toString()
for (Enum<?> e : constants) {
if (e.toString().equalsIgnoreCase(value)) {
return (T) e;
}
}
return null;
}
@Override
public String toString(final T value) {
return value != null ? value.toString() : null;
}
};
}
}
我正在使用这样的@BeanParam:
@GET
public Response listAllPaged(@BeanParam PagedRequest pagedRequest) {
// Do stuff...
}
bean 本身:
public class PagedRequest {
@QueryParam("sortOrder")
@DefaultValue("0")
public int sortOrder;
}
现在我想将 sortOrder 的类型更改为以下枚举:
public enum SortOrder {
ASC("asc"),
DESC("desc");
public final String sortOrder;
SortOrder(String sortOrder) {
this.sortOrder = sortOrder;
}
}
但是一旦我这样做:
public class PagedRequest {
@QueryParam("sortOrder")
@DefaultValue("asc")
public SortOrder sortOrder;
}
我的 REST 端点无法再匹配签名和 returns 404。这是为什么?我认为接受单个字符串的构造函数的存在应该允许 JAX-RS 进行转换。
我做错了什么?
更新
我设法让它像这样工作,但它并没有真正回答我最初的问题...
public enum SortOrder {
ASC,
DESC;
public static SortOrder fromString(String param) {
String toUpper = param.toUpperCase();
try {
return valueOf(toUpper);
} catch (Exception e) {
return null;
}
}
}
Enum.valueOf(String)
方法用于解析值。由于您的 SorterOrder
枚举是大写的,因此您需要以大写形式发送参数。
如果您只想传递小写的值,您可以将枚举名称更改为小写,例如SortOrder.asc
.
如果您不知道或不想关心参数发送的大小写,您可以使用 ParamConverter
.
public class SortOrderParamConverter implements ParamConverter<SortOrder> {
@Override
public SortOrder fromString(final String value) {
if (value != null) {
return SortOrder.valueOf(value.toUpperCase(Locale.ROOT));
}
return SortOrder.ASC;
}
@Override
public String toString(final SortOrder value) {
return value.name();
}
}
如果您想要更通用的方法,您可以创建一个 ParamConverter
或所有枚举。
@Provider
public class EnumParamConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(final Class<T> rawType, final Type genericType,
final Annotation[] annotations) {
if (!rawType.isEnum()) {
return null;
}
final Enum<?>[] constants = (Enum<?>[]) rawType.getEnumConstants();
return new ParamConverter<T>() {
@Override
@SuppressWarnings("unchecked")
public T fromString(final String value) {
if (value == null || value.isEmpty()) {
return null;
}
for (Enum<?> e : constants) {
if (e.name().equalsIgnoreCase(value)) {
return (T) e;
}
}
// No match, check toString()
for (Enum<?> e : constants) {
if (e.toString().equalsIgnoreCase(value)) {
return (T) e;
}
}
return null;
}
@Override
public String toString(final T value) {
return value != null ? value.toString() : null;
}
};
}
}