ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 세션 인증 때 커스텀 애노테이션 적용하기
    개발/Spring 2023. 6. 26. 12:34
        @GetMapping("/")
        public String homeLoginV3Spring(@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember, Model model) {
    
            if (null == loginMember) {
                return "home";
            }
    
            model.addAttribute("member", loginMember);
            return "loginHome";
        }

    @SessionAttribute를 이용하는 코드만 해도 충분히 간편하지만 ArgumentResolver를 사용하면 더 간단하게 코드를 줄일 수 있다.

        @GetMapping("/")
        public String homeLoginV3ArgumentResolver(@Login Member loginMember, Model model) {
    
            if (null == loginMember) {
                return "home";
            }
    
            model.addAttribute("member", loginMember);
            return "loginHome";
        }

    @Login 애노테이션을 만들고 해당 기능을 수행할 수 있도록 하면 된다.

    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 {}

    파라미터에 붙을 애노테이션이므로 PARAMETER 타입을 선택하고, 런타임 내내 유지되어야 하므로 RUNTIME 정책을 선택한다. 핵심 기능은 ArgumentResolver에서 작성한다. HandlerMethodArgumentResolver를 상속받아 구현하며 되고 큰 틀에서의 동작은 핸들러 어댑터와 비슷하다. 리졸버를 실행 여부를 결정할 supportsParameter를 오버라이드하고 비즈니스 로직은 resolverArgument에 작성한다.

    package hello.login.web.argumentresolver;
    
    import hello.login.domain.member.Member;
    import hello.login.web.SessionConst;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    import jakarta.servlet.http.HttpSession;
    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;
    
    @Slf4j
    public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
        @Override
        public boolean supportsParameter(MethodParameter parameter) {       
    
            boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class);
            boolean hadMemberType = Member.class.isAssignableFrom(parameter.getParameterType());
    
            return hasLoginAnnotation && hadMemberType;
        }
    
        @Override
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    
            HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
            HttpSession session = request.getSession(false);
            if (null == session) {
                return null;
            }
    
            return session.getAttribute(SessionConst.LOGIN_MEMBER);
        }
    }

    - parameter.hasParameterAnnotation(Login.class)

    MethodParameter는 핸들러의 매개변수 정보를 담고 있다. 여기에선 member를 의미할 거고, 그 파라미터에 @Login이 사용됐는지 여부를 확인한다

    - Member.class.isAssignableFrom(parameter.getParameterType())

    isAssignableFrom 메서드는 매개변수의 타입이 좌측의 subclass, subinterface인지 검사해준다. 같아도 true가 반환된다

    이 두 조건 모두가 참일 때 resolveArgument가 호출된다

    댓글

Designed by Tistory.