Spring's @RequestParam with Enum

匿名 (未验证) 提交于 2019-12-03 02:50:02

问题:

I have this enum :

public enum SortEnum {     asc, desc; } 

That I want to use as a parameter of a rest request :

@RequestMapping(value = "/events", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public List<Event> getEvents(@RequestParam(name = "sort", required = false) SortEnum sort) { 

It works fine when I send these requests

/events  /events?sort=asc /events?sort=desc 

But when I send :

/events?sort=somethingElse 

I get a 500 response and this message in the console :

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 

Is there a way to prevent spring from throwing these exceptions and set the enum to null ?

EDIT

The Strelok's accepted answer works. However, I decided to deal with handling the 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);     } 

回答1:

You can create a custom converter that will return null instead of an exception when an invalid value is supplied.

Something like this:

@Configuration public class MyConfig extends WebMvcConfigurationSupport {    @Override    public FormattingConversionService mvcConversionService() {        FormattingConversionService f = super.mvcConversionService();        f.addConverter(new MyCustomEnumConverter());        return f;    } } 

And a simple converter might look like this:

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        }     } } 


回答2:

you need to do the following

@InitBinder public void initBinder(WebDataBinder dataBinder) {     dataBinder.registerCustomEditor(YourEnum.class, new YourEnumConverter()); } 

refer the following : https://machiel.me/post/java-enums-as-request-parameters-in-spring-4/



回答3:

The answers provided so far are not complete. Here is an answer example step-by-step that worked for me:-

1st Define the enum in your endpoint signature(subscription type).
Example:

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, 

2nd Define a custom property editor that will be used to translate from String to enum:

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);         }     } } 

3rd Register the property editor with the controller:

@InitBinder ("subscriptiontype") public void initBinder(WebDataBinder dataBinder) {     dataBinder.registerCustomEditor(SubscriptionType.class, new SubscriptionTypeEditor()); } 

Translations from string to enum should happen perfectly now.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!