ArgumentResolver란?
@RestController
class UserController {
@GetMapping("/user/{userId}")
fun getUser(
@PathVariable userId: Long << 여기
) {
// ...
}
}
controller에 @PathVariable을 붙이면 path에서 자동으로 파라미터에 맵핑을 해주는데 이걸 바로 ArgumentResolver가 해준다.
(@PathVariable는 PathVariableMethodArgumentResolver.java에서 처리)
@RequestParam, @RequestBody도 마찬가지다.
그럼 이걸 누가 호출할까?
바로 핸들러 어댑터가 호출한다.
핸들러 어댑터가 핸들러를 호출할 때 핸들러의 파라미터를 읽어 그에 해당하는 ArgumentResolver를 찾아서 호출한다.
ArgumentResolver 추가 방법
스프링에서 우리가 필요한 대부분을 추가해놔서 거의 추가할 일이 없지만 가끔 쓸일이 있다.
header에 token을 받아 UserInfoResponse를 만들어주는 ArgumentResolver를 추가하는 걸 예시로 설명하겠다.
@RestController
class UserController {
@GetMapping("/user")
fun getUser(
user: UserInfoResponse << token 헤더를 읽어 UserInforResponse 생성
): UserInfoResponse {
return user
}
}
추가 방법은 다음과 같다.
ArugmentResolver 정의 -> WebMvcConfigurer에 추가
정말 간단하다.
1. ArgumentResolver 정의
HandlerMethodArgumentResolver를 구현한 클래스를 만들어야 한다.
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
@Nullable
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}
구현해야 할 메소드는 2개다.
supportsParameter : 어떤 파라미터를 처리할 건지
resolveArgument : 어떤 값을 만들 건지
header에 token 값을 읽어서 해당 유저 정보를 리턴해주는 UserInfoArgumentResolver를 만들어보자.
@Component
class UserInfoArgumentResolver(
val userRepository: UserRepository
): HandlerMethodArgumentResolver {
override fun supportsParameter(parameter: MethodParameter): Boolean {
return parameter.parameterType == UserInfoResponse::class.java // 타입
|| parameter.hasMethodAnnotation(UserInfo::class.java) // 어노테이션
}
override fun resolveArgument(
parameter: MethodParameter,
mavContainer: ModelAndViewContainer?,
webRequest: NativeWebRequest,
binderFactory: WebDataBinderFactory?
): Any? {
val token = webRequest.getHeader("token") as String
val user = userRepository.findByToken(token)
return UserInfoResponse(
id = user.id,
name = user.name
)
}
}
2. WebMvcConfigurer에 추가
WebMvcConfigurer를 구현한 클래스를 만들어야 한다.
위에서 만든 UserInfoArgumentResolver를 추가해보겠다.
@Component
class WebMvcConfig(
val userInfoArgumentResolver: UserInfoArgumentResolver
): WebMvcConfigurer {
override fun addArgumentResolvers(resolvers: MutableList<HandlerMethodArgumentResolver>) {
resolvers.add(userInfoArgumentResolver)
}
}
※ 결과
위에서 정의한 ArgumentResolver가 정상적으로 동작하는지 보자.
- request
curl --location --request GET 'http://localhost:8080/user' \
--header 'token: ASDA1321DKDL'
- response
{
"id": 1,
"name": "유저명"
}
잘 동작한다.
'Spring' 카테고리의 다른 글
[Spring] "has been compiled by a more recent version" 에러 처리 방법 (0) | 2022.12.19 |
---|---|
[Spring] ReturnValueHandler 추가 방법 (kotlin ver.) (0) | 2022.12.18 |
[Spring] 코틀린 springdoc-openapi 클래스명 중복 처리 방법 (0) | 2022.09.09 |
[Spring] 코틀린 springdoc-openapi, swagger - enum 소문자, 원하는 값으로 보여주기 (0) | 2022.09.09 |
[Spring] API 문서화(apidoc, swagger) 라이브러리 비교 - springfox vs springdoc-openapi (0) | 2022.09.08 |
댓글