Spring Framework

Web Controller @PathVariable Enum Class 변환 - Converter

sebastiano 2024. 1. 11. 18:53

개요

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