-
세션 인증 때 커스텀 애노테이션 적용하기개발/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가 호출된다
'개발 > Spring' 카테고리의 다른 글
@Transactional 적용 레벨 (0) 2023.07.05 application.properties의 유용한 설정 (0) 2023.06.26 Validation에서 에러 문구 설정 (0) 2023.06.20 컨트롤러(핸들러)가 조회되는 과정 (2) 2023.06.11 빈 스코프(Singleton, Prototype) (1) 2023.05.16