spring boot

어노테이션을 이용해 메소드 인자로 세션값 바로 받기 @LoginUser

원코드 2023. 4. 19. 13:27

'스프링 부트와 AWS로 혼자 구현하는 웹 서비스' - 이동욱 지음 

위의 책 일부를 공부용으로 정리한 내용입니다.

 

컨트롤러에서 로그인한 유저의 세션값을 가져오기 위해 아래 코드를 작성해야한다.

SessionUser User = (SessionUser) httpSession.getAttribute("user");

같은 코드가 반복되는 것을 피하기 위해 어노테이션을 통해 메소드 인자로 전달받는 형태로 변경하고자 한다.

 

@LoginUser 어노테이션 생성

config.auth 패키지에 LoginUser 생성

package com.odog.www.config.auth;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER) //1
@Retention(RetentionPolicy.RUNTIME) 
public @interface LoginUser { //2

}

1. 어노테이션이 생성될 수 있는 위치를 parameter로 지정

2. @interface를 통해 해당 파일을 어노테이션 클래스로 지정함. LoginUser라는 어노테이션이 생성됨.

 

LoginUserArgumentResolver 생성

LoginUser와 같은 위치에 LoginUserArgumetResolver 생성. HandlerMethodArgumentResolver 인터페이스를 구현한 클래스이다. 

package com.odog.www.config.auth;

import com.odog.www.config.auth.dto.SessionUser;
import lombok.RequiredArgsConstructor;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
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.HttpSession;

@RequiredArgsConstructor
@Component
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {

    private final HttpSession httpSession;

    @Override //1
    public boolean supportsParameter(MethodParameter parameter) { 
        boolean isLoginUserAnnotation = parameter.getParameterAnnotation(LoginUser.class) != null;
        boolean isUserClass = SessionUser.class.equals(parameter.getParameterType());

        return isLoginUserAnnotation && isUserClass;
    }

    @Override //2
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        return httpSession.getAttribute("user");
    }
}

1. supportsParameter() : 컨트롤러 메서드의 특정 파라미터를 지원하는지 판단하는 메소드. 여기서는 파라미터에 @LoginUser 어노테이션이 붙어 있고, 파라미터 클래스 타입이 SessionUser.class 인 경우 true를 반환함.

 

2. resolveArgument() : 파라미터에 전달할 객체 생성. 여기서는 세션에서 "user" 객체를 가져옴

 

적용

@Controller
@RequiredArgsConstructor
public class GoalsController {

    private final GoalsService goalsService;

    @ResponseBody
    @PostMapping("/goals")
    public Long save(@RequestBody GoalsSaveRequestDto requestDto, @LoginUser SessionUser user) {
        return goalsService.save(requestDto, user.getId());
    }

session의 "user" 정보가 @LoginUser 어노테이션을 통해 SessionUser 클래스에 담겨 파라미터를 통해 전달된다.