는 사실 Pageable 하면서 여러번 해봤는데 이번에 할 건 다음과 같다.
- 파라미터 모델이 졸라 많다.
- 각 파라미터 모델은 일부 intersection들이 있다.
- 각 프로퍼티의 역직렬화/직렬화 키는 같을 수도 있고 다를 수도 있다.
이럴때는 상속을 쓰는게 제일 나은데 인터페이스에 JsonProperty를 적용하면 그게 그걸 구현하는 클래스에서도 유지되는지 아리까리해서 그냥 간단하게 테스트…
일단 직렬화/역직렬화 키가 다르므로 이건 getter와 setter로 나눠서 JsonProperty를 설정하면 된다.
코틀린의 인터페이스는 프로퍼티를 가질 수 있으므로 @get:JsonProperty와 @set:JsonProperty는 쓸 수 있으나 @param:JsonProperty (생성자 프로퍼티용)은 붙일 수 없다. 따라서 이러한 인터페이스는 일반 클래스를 써야 하고 데이터 클래스로는 구현할 수 없다.
그래서 코드
@Target(AnnotationTarget.VALUE_PARAMETER)
@Retention(AnnotationRetention.RUNTIME)
annotation class QueryObject
구현할 MethodHandlerArgumentResolver에서 역직렬화할 파라미터를 구분하는 용도로 사용할 어노테이션이다.
class QueryObjectResolver(private val objectMapper: ObjectMapper): HandlerMethodArgumentResolver {
override fun supportsParameter(parameter: MethodParameter): Boolean {
return parameter.hasParameterAnnotation(QueryObject::class.java)
}
override fun resolveArgument(parameter: MethodParameter, mavContainer: ModelAndViewContainer?, webRequest: NativeWebRequest, binderFactory: WebDataBinderFactory?): Any? {
return if (webRequest is ServletWebRequest) {
val queryParams = webRequest.parameterMap.mapValues { it.value.firstOrNull() }
objectMapper.convertValue(queryParams, parameter.nestedParameterType)
} else {
null
}
}
}
역직렬화하는애다. 사실 resolveArgument 쪽은 좀 더 복잡해야하나 테스트용으로 간단하게 만들었다. 얘는 WebMvcConfigurerer의 addArgumentResolvers에 넣어주면 된다.
interface CommonParams {
@set:JsonProperty("foo")
@get:JsonProperty("bar")
var testParam: String?
}
class CommonParamsImpl: CommonParams {
override var testParam: String? = null
}
쿼리 파라미터 키는 foo이지만 객체화한 이후로는 bar로 넘기게 만든다.
@RestController
@RequestMapping("/test")
class TestController {
@GetMapping
fun test(@QueryObject queryObject: CommonParamsImpl) = queryObject
}
테스트 컨트롤러다. 그 다음 /test?foo=2로 요청하면
{
"bar": 2
}
가 나온다.
끗.
답글 남기기