私はこの列挙型を持っています:
public enum SortEnum {
asc, desc;
}
残りのリクエストのパラメータとして使用したいこと:
@RequestMapping(value = "/events", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public List<Event> getEvents(@RequestParam(name = "sort", required = false) SortEnum sort) {
これらのリクエストを送信するとうまくいきます
/events
/events?sort=asc
/events?sort=desc
しかし、私が送るとき:
/events?sort=somethingElse
コンソールに500応答とこのメッセージが表示されます。
2016-09-29 17:20:51.600 DEBUG 5104 --- [ XNIO-2 task-6] com.myApp.aop.logging.LoggingAspect : Enter: com.myApp.web.rest.errors.ExceptionTranslator.processRuntimeException() with argument[s] = [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type [Java.lang.String] to required type [com.myApp.common.SortEnum]; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [Java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam com.myApp.common.SortEnum] for value 'somethingElse'; nested exception is Java.lang.IllegalArgumentException: No enum constant com.myApp.common.SortEnum.somethingElse]
2016-09-29 17:20:51.600 DEBUG 5104 --- [ XNIO-2 task-6] com.myApp.aop.logging.LoggingAspect : Exit: com.myApp.web.rest.errors.ExceptionTranslator.processRuntimeException() with result = <500 Internal Server Error,com.myApp.web.rest.errors.ErrorVM@1e3343c9,{}>
2016-09-29 17:20:51.601 WARN 5104 --- [ XNIO-2 task-6] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type [Java.lang.String] to required type [com.myApp.common.SortEnum]; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [Java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam com.myApp.common.SortEnum] for value 'somethingElse'; nested exception is Java.lang.IllegalArgumentException: No enum constant com.myApp.common.SortEnum.somethingElse
Springがこれらの例外をスローするのを防ぎ、enumをnullに設定する方法はありますか?
編集
Strelokの受け入れられた答えは機能します。ただし、MethodArgumentTypeMismatchExceptionの処理に対処することにしました。
@ControllerAdvice
public class ExceptionTranslator {
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
@ResponseBody
public ResponseEntity<Object> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
Class<?> type = e.getRequiredType();
String message;
if(type.isEnum()){
message = "The parameter " + e.getName() + " must have a value among : " + StringUtils.join(type.getEnumConstants(), ", ");
}
else{
message = "The parameter " + e.getName() + " must be of type " + type.getTypeName();
}
return buildResponse(HttpStatus.UNPROCESSABLE_ENTITY, message);
}
無効な値が指定された場合、例外の代わりにnull
を返すカスタムコンバーターを作成できます。
このようなもの:
@Configuration
public class MyConfig extends WebMvcConfigurationSupport {
@Override
public FormattingConversionService mvcConversionService() {
FormattingConversionService f = super.mvcConversionService();
f.addConverter(new MyCustomEnumConverter());
return f;
}
}
そして、単純なコンバーターは次のようになります。
public class MyCustomEnumConverter implements Converter<String, SortEnum> {
@Override
public SortEnum convert(String source) {
try {
return SortEnum.valueOf(source);
} catch(Exception e) {
return null; // or SortEnum.asc
}
}
}
あなたは次のことをする必要があります
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
dataBinder.registerCustomEditor(YourEnum.class, new YourEnumConverter());
}
以下を参照してください: https://machiel.me/post/Java-enums-as-request-parameters-in-spring-4/
Spring Bootを使用している場合、 これが理由ですWebMvcConfigurationSupport
を使用しないでください。
ベストプラクティスとして、インターフェースorg.springframework.core.convert.converter.Converter
を実装し、注釈@Component
を実装する必要があります。その後、Spring BootはすべてのConverter
のBeanを自動的にロードします。 スプリングブートコード
@Component
public class GenderEnumConverter implements Converter<String, GenderEnum> {
@Override
public GenderEnum convert(String value) {
return GenderEnum.of(Integer.valueOf(value));
}
}
これまでに提供された回答は完全ではありません。ここに私のために働いたステップバイステップの答えの例があります:
最初に、エンドポイントシグネチャ(サブスクリプションタイプ)で列挙型を定義します。
例:
public ResponseEntity v1_getSubscriptions(@PathVariable String agencyCode,
@RequestParam(value = "uwcompany", required = false) String uwCompany,
@RequestParam(value = "subscriptiontype", required = false) SubscriptionType subscriptionType,
@RequestParam(value = "alert", required = false) String alert,
2番目は、文字列から列挙型への変換に使用されるカスタムプロパティエディターを定義します。
import Java.beans.PropertyEditorSupport;
public class SubscriptionTypeEditor extends PropertyEditorSupport {
public void setAsText(String text) {
try {
setValue(SubscriptionType.valueOf(text.toUpperCase()));
} catch (Exception ex) {
setValue(null);
}
}
}
3番目のプロパティエディターをコントローラーに登録します。
@InitBinder ("subscriptiontype")
public void initBinder(WebDataBinder dataBinder) {
dataBinder.registerCustomEditor(SubscriptionType.class, new SubscriptionTypeEditor());
}
文字列から列挙型への翻訳は完全に行われるはずです。
String
paramの代わりにSortEnum
を使用できます
@RequestParam(name = "sort", required = false) String sort
そしてそれを使用して変換する
SortEnum se;
try {
se = SortEnum.valueOf(source);
} catch(IllegalArgumentException e) {
se = null;
}
getEvents(...)エンドポイントメソッドの内部では、優雅さは失われますが、変換と起こりうるエラー処理をさらに制御できます。