전 시간에 Controller에서 Session을 가져오는 데 있어서 중복 코드가 있었습니다. 해당 코드를 ArgumentResolver로 해결해보겠습니다. 

 

ArgumentResolver란? 

컨트롤러의 메소드의 인자로 사용자가 임의의 값을 전달하는 방법을 제공할 때 사용합니다. 저희가 활용할 부분은 세션에 저장되어 있는 것을 메소드의 파라미터로 넘겨주는 역할을 하게 됩니다.


1. argumentresolver 패키지 먼저 만듭니다. 

SessionConst와 SessionDto를 사용하므로 Dto에 있던 것을 옮겨줍니다.

2. ArgumentResolver에 사용될 LoginUser Annotation만들기

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
  • @Target: Annotation을 사용할 수 있는 곳을 정의합니다. Class, Parameter,Method,Field 등등 여러 가지 있습니다.
  • @Retention: Annotation의 설정으로 Annotation의 라이프 사이클을 정의합니다. Source, Class, Runtime이 있습니다. 보통 Runtime을 사용하여 프로젝트가 실행 중에도 사용할 수 있도록 Annotation의 라이프 사이클을 정해줍니다. 

3. ArgumentResolver

public class ArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
parameter.hasParameterAnnotation(LoginUser.class);
boolean hasLoginAnnotation = parameter.hasParameterAnnotation(LoginUser.class);
boolean hasOwnerType = SessionDto.class.isAssignableFrom(parameter.getParameterType());
return hasLoginAnnotation && hasOwnerType;
}
@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(session==null){
return null;
}
return session.getAttribute(SessionConst.LOGIN_MEMBER);
}
}

 

  • supportsParameter: 우리가 받고자 파라미터가 조건을 만족하는지 확인합니다. 조건을 만족시키지 못할 시 false를 반환하며, resolveArgument()를 실행하지 않습니다.

     1. @LoginUser Annotation이 붙었는지 확인합니다. 

     2. 정보를 넣고자 하는 SessionDto 클래스인지 확인합니다. 

 

  • resolveArgument: supportsParameter에서 true가 넘어올 시 실행됩니다.

     1. NativeWebRequest를 HttpServletRequest로 형변환 합니다.

     2. request.getSession(false)로 하여 session이 없다면 생성하지 않습니다. 

     3. session이 있다면 로그인을 기존에 한 user이므로 session.getAttribute(SessionConst.LOGIN_MEMBER)를 실행하여 SessionDto에 정보를 넣어주는 역할을 하게 됩니다.

 

4. MVC에서 사용할 수 있도록 WebConfig에 등록해줍니다.

 패키지와 WebConfig를 생성해줍니다. 

@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new ArgumentResolver());
}
}
  • WebMvcConfigurer를 상속받고, addArugmentResolvers를 Override 하여 저희가 만든 ArgumentResolver를 추가해줍니다. 

5. MemberController변경

@RestController
@RequiredArgsConstructor
@RequestMapping("/member")
public class MemberController {
private final MemberService memberService;
@PostMapping("/request/{teamId}")
public Long requestTeam(@PathVariable(name = "teamId")Long teamId,@LoginUser SessionDto sessionUser){
Long okId = memberService.requestTeam(teamId,sessionUser.getId());
return okId;
}
@GetMapping("/request")
public List<RequestTeamDto> requestList(@LoginUser SessionDto sessionUser){
return memberService.findRequestList(sessionUser.getId());
}
@DeleteMapping("/request/{teamId}")
public String deleteRequest(@PathVariable(name = "teamId") Long teamId,@LoginUser SessionDto sessionUser){
memberService.WithdrawalTeamRequest(sessionUser.getId(),teamId);
return "ok";
}
@DeleteMapping("/request")
public String leavingTeam(@LoginUser SessionDto sessionUser){
memberService.leavingTeam(sessionUser.getId());
return "ok";
}
}

6. Postman을 이용해서 테스트해보겠습니다.

 

회원 가입을 진행해줍니다.

로그인을 하기 전에는 Session이 없기 때문에 Cookies에 아무런 내용이 없습니다. 

로그인 요청을 보낸 후 성공했습니다. 그리고 Session이 생성된 것을 알 수 있습니다.

 

ArgumentResolver가 잘 작동하는지 알아보기 위해서 Member가 팀 가입 신청한 리스트를 찾는 로직을 실행합니다. Team이 아직 생성되지 않아도 가능하므로 잘 작동한다면 [] 비어있는 List를 받으며 

  1. Get localhost/member/request 요청 보냅니다.
  2. Team이 아직 생성되지 않아도 가능하므로 잘 작동한다면 [] 비어있는 List를 받습니다.
  3. 작동하지 않는다면 Member를 찾을 수 없는 오류를 터뜨릴 것입니다.

ArgumentResolver가 잘 작동하여 빈 List를 받은 것을 확인할 수 있습니다. 

 

지금까지 Annotation을 활용한 ArgumentResolver를 만들어봤습니다. 저희는 로그인만 성공하면 Member에 관한 모든 로직을 사용할 수 있는 형태였습니다. 하지만 TeamFounder나 LeagueHost의 역할을 가진 다른 User는 사용하지 못하도록 Interceptor를 만들어보겠습니다. 감사합니다. 

 

모든 코드는 아래 링크에서 확인 가능합니다.

https://github.com/rlaehdals/blogProject

 

GitHub - rlaehdals/blogProject

Contribute to rlaehdals/blogProject development by creating an account on GitHub.

github.com