ArgumentResolver
ArgumentResolver(정확히 HandlerMethodArgumentResolver)는 핸들러 메서드에서 사용되는 다양한 인자를 생성해 제공해주는 역할을 맡는다. 스프링이 기본으로 제공해주는 ArgumentResolver도 있지만 프로그래머가 직접 커스텀 ArgumentResolver를 만들어 핸들러 메서드에서 자신이 원하는 인자를 받을 수 있다.
아래는 세션 키를 받아 키에 해당하는 세션 데이터가 있으면(로그인 된 사용자이면) loginHome 뷰를, 세션 데이터가 없으면(로그인 되지 않은 사용자이면) Home 뷰를 응답하는 간단한 핸들러 메서드이다. 핸들러 메서드의 인자가 살짝 길어 가독성이 떨어진다. 커스텀 ArgumentResolver를 만들어 이를 해결해보자.
@GetMapping("/")
public String homeLoginV3Spring(
@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember, Model model) {
if(loginMember == null) {
return "home";
}
model.addAttribute("member", loginMember);
return "loginHome";
}
1. 핸들러 메서드 인자에서 사용할 로그인 애노테이션 생성
package hello.login.web.argumentResolver;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Login {
}
2. 커스텀 ArgumentResolver 구현
package hello.login.web.argumentResolver;
import hello.login.domain.member.Member;
import hello.login.web.SessionConst;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
@Slf4j
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
log.info("supportsParameter 실행");
boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class);
boolean hasMemberType = Member.class.isAssignableFrom(parameter.getParameterType());
return hasLoginAnnotation && hasMemberType;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
log.info("resolverArgument 실행");
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
HttpSession session = request.getSession(false);
if(session == null) {
return null;
}
return session.getAttribute(SessionConst.LOGIN_MEMBER);
}
}
스프링은 resolveArgument()에서 반환한 객체를 핸들러 메서드의 인자로 전달한다.
3. 커스텀 ArgumentResolver 등록
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new LoginMemberArgumentResolver());
}
}
4. 로그인 애노테이션 사용
@GetMapping("/")
public String homeLoginV3ArgumentResolver(@Login Member loginMember, Model model) {
if(loginMember == null) {
return "home";
}
model.addAttribute("member", loginMember);
return "loginHome";
}
위의 homeLoginV3Spring 핸들러보다 인자 부분이 간단해졌고 Login 애노테이션을 재사용할 수 있게 되었다.
'Spring > Spring MVC' 카테고리의 다른 글
API 예외 처리 (0) | 2023.04.19 |
---|---|
예외 처리와 오류 페이지 (0) | 2023.04.17 |
스프링 Filter, Interceptor (0) | 2023.04.14 |
스프링 검증 (2) (0) | 2023.04.02 |
스프링 검증 (1) (0) | 2023.03.27 |