HandlerMethodArgumentResolver :
Strategy interface for resolving method parameters into argument values in the context of a given request.
메소드 매개변수를 확인하고, 이를 HTTP 요청을 바탕으로 인수 값 (argument value) 으로 변환하는 역할을 합니다. 즉 어떻게 '메서드 파라미터'를 적합한 '인수 값'으로 변환할지"를 결정하는 인터페이스입니다. 우리는 구현체를 만들어 사용하면 되겠습니다.
메서드 매개변수와 인수값이 무엇을 의미하는 걸까요 ?
@GetMapping("/profile")
public ResponseEntity<ProfileResponse> getProfile(VerifiedMember verifiedMember) {
// ...
}
메소드 매개변수란 VerifiedMember verifiedMember
입니다.
인수값에 대해 설명하겠습니다. 위 메서드가 실행될 때 ArgumentResolver에 의해 verifiedMember에 들어갈 객체
가 생성됩니다. 이때 그 객체를 인수값이라 부릅니다.
HandlerMethodArgumentResolver는 2개의 메서드로 구성되어 있습니다.
1.
boolean supportsParameter(MethodParameter parameter);
메서드의 파라미터가 resolver 의 지원을 받는지, 그 여부에 관한 것입니다.
parameter 를 확인하여 지원을 받는다면 true, 아니라면 false를 반환합니다.
실제 사용
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(VerifiedMember.class);
}
2.
@Nullable
Object resolveArgument(
MethodParameter parameter,
@Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@Nullable WebDataBinderFactory binderFactory) throws Exception;
컨트롤러 메서드의 특정 파라미터에 인수 값을 생성 및 할당합니다. 이때 인수 값은 HTTP 요청으로부터 만들어집니다.
따라서 parameter 와 webReauest 는 반드시 필요합니다(@Nullable 이 아닌 것입니다) !!
실제 사용
@Override
public Object resolveArgument(
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory
) {
HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest();
String headerToken = request.getHeader(AUTHORIZATION_HEADER);
String token = jwtUtil.substringToken(headerToken);
Claims memberClaims = jwtUtil.getMemberClaims(token);
Long memberId = Long.parseLong(memberClaims.getSubject());
String email = (String)memberClaims.get("email");
return VerifiedMember.builder()
.id(memberId)
.email(email)
.build();
}
제대로 동작하기 위해서 명시적으로 ArgumentResolver 를 스프링(의 여러 Resolver 중)에 추가해야 하며, 그러기 위해선 빈으로 등록해야 합니다.
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final MemberArgumentResolver memberArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(memberArgumentResolver);
}
}
구현체:
@Component
@RequiredArgsConstructor
public class MemberArgumentResolver implements HandlerMethodArgumentResolver {
private static final String AUTHORIZATION_HEADER = "Authorization";
private final JwtUtil jwtUtil;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().equals(VerifiedMember.class);
}
@Override
public Object resolveArgument(
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory
) {
HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest();
String headerToken = request.getHeader(AUTHORIZATION_HEADER);
String token = jwtUtil.substringToken(headerToken);
Claims memberClaims = jwtUtil.getMemberClaims(token);
Long memberId = Long.parseLong(memberClaims.getSubject());
String email = (String)memberClaims.get("email");
return VerifiedMember.builder()
.id(memberId)
.email(email)
.build();
}
}
공식 문서
'Spring > Spring 문법' 카테고리의 다른 글
JPA 레벨 vs 데이터베이스 레벨 (feat.성능) (0) | 2024.12.21 |
---|---|
@Scheduler 사용해보기(주기 마다 메서드 실행) (0) | 2024.12.09 |
Pageable 과 PagedModel (1) | 2024.12.09 |
Mock 을 이용한 테스트 코드 - argument matcher (0) | 2024.11.26 |
N + 1 문제 해결, JPQL과 QueryDsl에서 JOIN FETCH (0) | 2024.11.26 |