Springあるある
원하는 기능을 Annotation을 만들어서 활용하기(Feat. ArgumentResolver,Login, @Login)
JIN_YOUNG _KIM
2025. 1. 17. 15:22
우리는 아래의 코드와 같이 @Login 애노테이션이 붙어 있으면 해당 회원(Member)가 로그인된 회원인지 아닌 지를
판단한 후, 컨트롤러 매개변수인 Member member에 값을 매핑하는 기능을 만들고 싶다.
이때 사용되는 스프링 인터페이스가 바로 ArgumentResolver이다.
@Slf4j
@Controller
@RequiredArgsConstructor
public class HomeController {
@GetMapping("/")
public String homeLoginV3SpringArgumentResolver(@Login Member loginMember, Model model)
{
if(loginMember == null)
return "home";
// 세션이 유지되면 로그인으로 이동동
model.addAttribute("member",loginMember);
return "loginHome";
}
}
@Target(ElementType.PARAMETER) // @Login Annotation의 target은 매개변수(Parameber)
@Retention(RetentionPolicy.RUNTIME) // retention : 유지
public @interface Login {
}
@Slf4j
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
log.info("supportsParamter() 실행 시작");
// 1. 컨트롤러 메서드의 매개변수(Paramter)에 @Login 애노테이션이 있는 지 여부
boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class);
// 2. @Login이 붙어 있는 매개변수가 Member 타입인지를 체크
boolean hasMemberType = Member.class.isAssignableFrom(parameter.getParameterType());
// 1과 2를 모두 만족하면 resolveArgument() 실행
return hasLoginAnnotation && hasMemberType;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
log.info("resolveArgument() 실행");
HttpServletRequest request = (HttpServletRequest)webRequest.getNativeRequest();
HttpSession session = request.getSession(false);
if(session == null){
return null; // 해당 컨트롤러 메서드의 매개변수(Member)에 null을 매핑함!
}
// 해당 컨트롤러 메서드의 매개변수(Member)에 해당 세션 value를 매핑함!
return session.getAttribute(SessionConst.LOGIN_MEMBER);
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new LoginMemberArgumentResolver());
}
}
이와 같이 공통 작업 같은 경우 ArgumentResolver를 이용하면 매우 편리하다
-> 개발자는 @Login만 컨트롤러에서 붙여주면 그만이다.
(물론 공통 기능은 서블릿 필터, 스프링 인터셉터를 이용해도 된다)