ArgumentResolver를 이용하여 중복 코드 제거

딸모붕·2023년 10월 9일

알고리즘 문제 출제 사이트를 구현하면서 인증된 사용자의 정보를 인가하는 로직이 매 페이지마다 필요했다.

이 로직을 모든 서비스 코드에서 작성하게 되면 너무 많은 코드 중복이 생긴다.

그래서 ArgumentResolver를 사용해 사용자 인증처리 중복 코드를 제거하였다.

ArgumentResolver

argumentResolver를 구현하기 전에 spring mvc가 어떻게 request를 처리하는지 알아야 한다.

  1. client가 웹 브라우저를 통해 dispatcherServlet으로 request를 보낸다.
  2. dispatcherServlet은 HandlerMapping에게 요청을 처리할 핸들러를 찾도록 위임한다.
    • RequestMapping으로 구현한 API 검색(RequestMappingHandlerAdapter)
    • 찾은 경우 Interceptor 처리 -> ArgumentResolver 처리 -> MessageConverter 처리를 한다.
  3. Controller Invoke

HandlerMethodArgumentResolver

Strategy interface for resolving method parameters into argument values in the context of a given request.

적용 코드

@Component
public class CustomMemberResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().equals(Member.class);
    }

    @Override
    public Object resolveArgument(
            MethodParameter parameter,
            ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest,
            WebDataBinderFactory binderFactory) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() instanceof CustomMemberDetails) {
            CustomMemberDetails customMemberDetails = (CustomMemberDetails) authentication.getPrincipal();
            return customMemberDetails.getMember();//Member 객체 리턴
        }
        return new EntityNotFoundException();
    }
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new CustomMemberResolver());//Resolver 추가
    }
}
@Target(ElementType.PARAMETER) // --- 1
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthUser {
	//어노테이션 추가
}

공통로직을 추출한 후 다음과 같이 컨트롤러에서 사용해주었다.

@PostMapping("/save")//질문 게시글 작성
    public ResponseEntity save(@RequestBody QuestionSaveDTO saveForm,@AuthUser Member member) 
    
@DeleteMapping("/{questionId}")
    public ResponseEntity deleteQuestion(@PathVariable("questionId") long questionId, @AuthUser Member member)    

0개의 댓글