Day 10

이전의 OAuth에서부터 진행

어노테이션 기반으로 개선

프로그래밍에서 코드의 개선이 필요할 때가 있다(나쁜코드)

대표적으로는 : 반복되는 같은 코드

우리의코드에서는 IndexController에서의 세션값을 가져오는 부분이 문제임

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

index 메소드 외의 다른 컨트롤러와 메소드에서 세션값이 필요하면 그 때마다 직접 세션에서 값을 가져와야함

그래서 이 부분을 메소드 인자로 세션값을 바로 받을 수 있도록 해보자

config.auth 패키지에 @LoginUser 어노테이션을 생성하자

→자바파일에서 Annotation을 만드는 곳이 있더라

src/main/java/com/kyu/book/springboot/config/auth/LoginUser

package com.kyu.book.springboot.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)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
  • @Target(ElementType.PARAMETER)

    • 이 어노테이션이 생성될 수 있는 위치를 지정

    • PARAMETER로 지정했으니 메소드의 파라미터로 선언된 객체에서만 사용할 수 있음

    • 이 외에도 클래스 선언문에서 쓸 수 있는 TYPE 등이 있음

  • @interface

    • 이 파일을 어노테이션 클래스로 지정한다

    • LoginUser라는 어노테이션이 생성되었다고 생각하면 된다

다음으로 같은 위치에 LoginUserArgumentResolver를 생성

→HandlerMethodArgumentResolver 인터페이스를 구현한 클래스

  • 조건에 맞는 경우 메소드가 있다면 HandlerMethodArgumentResolver의 구현체가 지정한 값으로 해당 메소드의 파라미터를 넘길 수 있음

src/main/java/com/kyu/book/springboot/config/auth/LoginUserArgumentResolver

package com.kyu.book.springboot.config.auth;

import com.kyu.book.springboot.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
    public boolean supportsParameter(MethodParameter parameter) {
        boolean isLoginUserAnnotation = parameter.getParameterAnnotation(LoginUser.class) != null;
        boolean isUserClass = SessionUser.class.equals(parameter.getParameterType());
        
        return isLoginUserAnnotation && isUserClass;
    }

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

    • 컨트롤러 메소드의 특정 파라미터를 지원하는지 판단

    • 여기서는 파라미터에 @LoginUser 어노테이션이 붙어 있고, 파라미터 클래스 타입이 SessionUser.class인 경우 true를 반환

  • resolveArgument()

    • 파라미터에 전달할 객체를 생성한다

    • 여기서는 세션에서 객체를 가져온다

—여기까지가 @LoginUser를 사용하기 위한 환경을 구성—

이제는 LoginUserArgumentResolver가 스프링에서 인식될 수 있도록 WebMvcConfigurer에 추가

config패키지의 webConfig 클래스를 생성해서 설정 추가

src/main/java/com/kyu/book/springbook/config/WebConfig

package com.kyu.book.springboot.config;

import com.kyu.book.springboot.config.auth.LoginUserArgumentResolver;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@RequiredArgsConstructor
@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final LoginUserArgumentResolver loginUserArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers){
        argumentResolvers.add(loginUserArgumentResolver);
    }
}
  • HandlerMethodArgumentResolver는 항상 WebMvcConfigurer의 addArgumentResolvers()를 통해서 항상 추가해야한다.

  • 다른 HandlerMethodArgumentResolver가 필요하다면 같은 방식으로 추가해주면 된다

—이걸로 모든 설정이 끝났으니까 IndexController의 코드에서 반복되는 부분을 모두 @LoginUser로 개선

src/main/java/com/kyu/book/springboot/web/dto/IndexController

private final PostsService postsService;

@GetMapping("/")
public String index(Model model, @LoginUser SessionUser user){
    model.addAttribute("posts", postsService.findAllDesc());
    if(user != null){
        model.addAttribute("userName", user.getName());
    }
    return "index";
}
  • @LoginUser Session user

    • 기존에 (User)httpSession.getAttribute("user")로 가져오던 세션정보 값을 이제 그 방식을 사용하지 않아도 가능

    • 이제는 어느 컨트롤러든지 @LoginUser만을 사용하게되면 세션의 정보를 가져와서 사용할 수 있다

Last updated

Was this helpful?