Web Controller @PathVariable Enum Class 변환 - Converter
개요
Spring Web Application 에서 Web Controller 에 @PathVariable 을 사용할 수 있다.
@PathVariable 로 전달 받을 수 있는 값을 Enum 으로 정의한 값만 사용하도록 제한하면 사용자의 Http Request 사용을 제한 하고자 할 때 유용하다.
일반적으로 Enum 을 정의 할 때는 대문자로 정의하는데, @PahtVariable 은 대소문자를 구분하기 때문에 Controller 를 호출 할 때 url path 에 반드시 대문자를 써야 하는 것은 좋지 않다.
이런 경우 Spring 에서 제공하는 Converter 를 이용하여 url path 의 소문자를 Enum Class 에 정의한 대문자로 변환하면서 Enum Class 로 @PathVariable 을 전달 받을 수 있다.
동작 방식 분석
Http Request 를 받는 Web Controller
Web Contoller 가 사용자 요청을 받는 http request url 에 @PathVariable 이 포함 되어 있다
Converter(Spring Converter implement)
Web Contoller 의 @PathVariable 을 Enum Class 로 변환하는 기능의 Convertor
- Spring Converter 를 Implement 하여 SpringToEnumConverter 구현
- Enum Class 를 return
- 변환 할 Enum 이 여러 개이면 Enum 마다 Converter 를 구현하고, 각각의 Converter 를 WebMvcConfigurer 에 등록해야 한다.
Enum Class
- @PathVariable 을 변환할 Enum Class
- 구현 되는 각각의 Converter 마다 사용 된다.
Web Controller 에 Convertor 적용 - WebMvcConfigurer
Spring MVC 를 적용(Spring WebMvcConfigurer 를 implements) 하는 Config Class 를 구현하고, @Configuration 어노테이션을 적용
Spring WebMvcConfigurer Interface 의 addFormatters 메서드를 @Override 하여 구현한 StringToEnumConverter 를 Spring FormatterRegistry 에 addConverter 로 등록(registry) 한다.
Converter 로 구현 되어 WebMvcConfigurer 에 의해 등록 된 Converter Bean 의 Enum Class는 Web Controller 에서 사용 될 때 Converter 가 적용 된다.
Controller 의 @PathVariable
Web Controller 에서 @PathVariable 을 Enum Class TypeCode 로 변환하는 코드
// Web Controller
@RequestMapping(value = "/{type}/balances", produces = MediaType.APPLICATION_JSON_VALUE, method = {RequestMethod.POST})
public JsonResult getTokenBalances(
@PathVariable(value = "type") TypeCode typeCode,
@RequestBody Login reqBody)
{
logger.debug("==> PathVariable(type) : {}", typeCode.toString());
}
@PathVariable 을 변환 할 Enum Class
Enum Class TypeCode
// Enum Class
@AllArgsConstructor
@Getter
public enum TypeCode {
TYPE_A("a", "type_a"),
TYPE_B("b", "type_b");
private final String code;
private final String codeValue;
private static final Map<String, TypeCode> typeCodeMap;
static {
typeCodeMap = Arrays.stream(TypeCode.values())
.collect(Collectors.toMap(TypeCode::getCode, Function.identity()));
}
public static TypeCode lookup(String code) {
return typeCodeMap.getOrDefault(code, TYPE_A);
}
}
Converter - @PathVariable String 을 Enum Class 로 변환
Spring 의 Converter 를 이용하여 소문자를 대문자로 변환
// Converter
public class StringToTypeCodeConverter implements Converter<String, TypeCode> {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Override
public TypeCode convert(String pathVariable) {
logger.debug("==> pathVariable : {}", pathVariable);
return TypeCode.lookup(pathVariable.toUpperCase());
}
}
converter 를 @Configuration 등록
구현한 Converter 를 @Configuration 으로 등록해야 Spring Application 이 기동할 때 적용 된다.
// Converter 를 WebMvcConfigurer 로 등록하는 @Configuration
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToTypeCodeConverter());
}
}