Spring的@RequestParam与Enum
我有这个枚举:
public enum SortEnum { asc, desc; }
我想用作rest请求的参数:
@RequestMapping(value = "/events", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public List 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 = 2016-09-29 17:20:51.601 WARN 5104 --- [ XNIO-2 task-6] .mmaExceptionHandlerExceptionResolver : 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抛出这些exception并将枚举设置为null?
编辑
Strelok接受的答案有效。 但是,我决定处理MethodArgumentTypeMismatchException。
@ControllerAdvice public class ExceptionTranslator { @ExceptionHandler(MethodArgumentTypeMismatchException.class) @ResponseBody public ResponseEntity 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
而不是exception。
像这样的东西:
@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 { @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/
到目前为止提供的答案并不完整。 以下是一个循序渐进的答案示例,对我有用: –
1st在端点签名中定义枚举(订阅类型)。
示例 :
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步定义将用于从String转换为枚举的自定义属性编辑器:
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()); }
从字符串到枚举的翻译现在应该完美地发生。