Enum이 있는 Spring의 @RequestParam
다음 항목이 있습니다.
public enum SortEnum {
asc, desc;
}
rest 요청의 파라미터로 사용하고 싶은 것:
@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
스프링이 이러한 예외를 발생시키지 않도록 하고 열거값을 null로 설정하는 방법이 있습니까?
편집
Strlok이 인정한 답변은 유효합니다.다만, MethodArgument를 취급하기로 했습니다.Type Mismatch Exception 입니다.
@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);
}
Spring Boot을 사용하고 있는 경우는, 이러한 이유로 를 사용하지 말아 주세요.WebMvcConfigurationSupport
프랙티스는 입니다.org.springframework.core.convert.converter.Converter
" " " 입니다. "@Component
것을 Converter
의 콩스프링 부트 코드
@Component
public class GenderEnumConverter implements Converter<String, GenderEnum> {
@Override
public GenderEnum convert(String value) {
return GenderEnum.of(Integer.valueOf(value));
}
}
할 수 .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/ 를 참조해 주세요.
여러 개의 enum이 있는 경우 다른 답변을 따를 경우 각 enum에 대해 하나의 변환기가 생성됩니다.
다음은 모든 Enum에 적합한 솔루션입니다.
Converter 또는 PropertyEditorSupport는 대상 클래스를 알 수 없으므로 이 경우에는 적합하지 않습니다.
이 예에서는 Jackson Object Mapper를 사용하고 있습니다만, 이 부분을 리플렉션에 의한 스태틱메서드에 대한 호출로 대체하거나 콜을 값()으로 변환기로 이동할 수 있습니다.
@Component
public class JacksonEnumConverter implements GenericConverter {
private ObjectMapper mapper;
private Set<ConvertiblePair> set;
@Autowired
public JacksonEnumConverter(ObjectMapper mapper) {
set = new HashSet<>();
set.add(new ConvertiblePair(String.class, Enum.class));
this.mapper = mapper;
}
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return set;
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
return null;
}
try {
return mapper.readValue("\"" + source + "\"", targetType.getType());
} catch (IOException e) {
throw new InvalidFieldException(targetType.getName(),source.toString());
}
}
}
이 경우 잭슨을 사용하고 있기 때문에 enum 클래스는 @JsonCreator에 주석을 단 정적 메서드를 가지고 있어야 합니다.그러면 상수 이름이 아닌 값을 사용하여 매핑할 수 있습니다.
public enum MyEnum {
VAL_1("val-1"), VAL_2("val-2");
private String value;
MyEnum(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)
public static MyEnum fromValue(String value) {
for (MyEnum e : values()) {
if (e.value.equalsIgnoreCase(value)) {
return e;
}
}
throw new InvalidFieldException("my-enum", value);
}
}
null을 반환하는 대신 예외를 두는 것이 좋습니다.
지금까지의 답변은 완전하지 않다.다음은 나에게 효과가 있었던 단계별 답변 예시입니다.-
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,
2nd 문자열에서 열거형으로 변환하는 데 사용되는 사용자 지정 속성 편집기를 정의합니다.
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 속성 편집기를 컨트롤러에 등록합니다.
@InitBinder ("subscriptiontype")
public void initBinder(WebDataBinder dataBinder) {
dataBinder.registerCustomEditor(SubscriptionType.class, new SubscriptionTypeEditor());
}
문자열에서 열거형으로의 변환은 이제 완벽하게 이루어집니다.
WebMvcConfigure 지원 대신 WebMvcConfigurer를 이미 구현하고 있는 경우 addFormatters 메서드를 구현하여 새로운 컨버터를 추가할 수 있습니다.
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new MyCustomEnumConverter());
}
사용할 수 있습니다.@JsonValue
주석을 지정합니다.체크해주세요 - https://www.baeldung.com/jackson-serialize-enums
2021년 8월 현재 일부 최신 Spring 버전을 사용하면 다음 코드가 가장 단순하고 작동합니다.유일한 까다로운 부분은 deserializeByName() 메서드입니다.이 메서드는 enum에 추가해야 하며 나머지 코드는 보통입니다.
public enum WorkplanGenerationMode {
AppendWorktypes("AppendWorktypes"),
New("New");
private String value;
WorkplanGenerationMode(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
@JsonCreator
public static WorkplanGenerationMode deserializeByName(@JsonProperty("name") String name) {
return WorkplanGenerationMode.valueOf(name);
}
}
그리고 다음 엔드포인트에 문자열 값이 입력되어 올바른 열거값으로 변환되고 Java 열거 멤버는 이 값을 사용하여 초기화됩니다.
public ResponseEntity<List<WorkplanGenerationProgressDTO>> generate(@RequestBody WorkplanFromBaseRequest request) {
NB! WorkplanGenerationMode는 다음과 같은 WorkplanFromBaseRequest 멤버의 한 종류입니다.
@Data
public class WorkplanFromBaseRequest {
private WorkplanGenerationMode mode;
사용할 수 있습니다.String
대신SortEnum
PARAM.
@RequestParam(name = "sort", required = false) String sort
를 사용하여 변환합니다.
SortEnum se;
try {
se = SortEnum.valueOf(source);
} catch(IllegalArgumentException e) {
se = null;
}
getEvents(...) 엔드포인트 메서드의 내부는 우아함을 잃었지만 변환 및 오류 처리를 보다 잘 제어할 수 있게 되었습니다.
언급URL : https://stackoverflow.com/questions/39774427/springs-requestparam-with-enum
'programing' 카테고리의 다른 글
Json의 getString()과 optString()의 차이점 (0) | 2023.03.31 |
---|---|
Swift 3에서 JSON 파일 읽기 (0) | 2023.03.31 |
Angular를 사용한 $http 동기 호출 방법JS (0) | 2023.03.31 |
정의되지 않은 속성 '이력'을 읽을 수 없습니다(React Router 5의 useHistory hook). (0) | 2023.03.31 |
부울 속성에 의한 "track by"를 사용한 각도 1.2ng 반복 필터링 (0) | 2023.03.31 |