반응형
어노테이션 기반으로 개선하기
- 반복되는 같은 코드 해결하기
- 커스텀 어노테이션(@LoginUser) 만들기
- ArgumentResolver
커스텀 어노테이션 생성
- 세션 처리를 위한 @LoginUser 어노테이션 생성
- @Target(ElementType.PARAMETER)
- 어노테이션이 생성될 수 있는 위치를 지정
- PARAMETER로 지정하므로써 메서드의 파라미터로 선언된 객체에서만 사용될 수 있다.
- 이 외에도 클래스 선언시 사용할 수 있는 TYPE 등이 있다.
- @Interface
- 해당 파일을 어노테이션 클래스로 지정
- LoginUser라는 이름을 가진 어노테이션을 사용할 수 있다.
- @Target(ElementType.PARAMETER)
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
LoginUserArgumentResolver
- ArgumentResolver 생성
- HandlerMethodArgumentResolver 인터페이스를 구현한 클래스
- 조건에 맞는 경우 메서드가 있다면, HandlerMethodArguementResolver의 구현체가 지정한 값으로 해당 메서드의 파리미터로 넘길 수 있다.
- supportParameter()
- 컨트롤러 메서드의 특정 파라미터를 지원하는지 판단
- 파라미터에 @LoginUser 어노테이션이 붙어있고, 파라미터 클래스 타입이 SessionUser.class인 경우 true를 반환
- resolveArgument()
- 파라미터에 전달할 객체를 생성
- 해당 코드에서는 세션에서 객체를 가져온다.
@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");
}
}
ArgumentResolver 설정
- WebConfig
- 스프링에서 LoginUserArgumentResolver를 인식할 수 있도록 WebMvcConfigurer를 구현한 WebConfig 클래스에 설정한다.
- WebMvcConfigurer의 addArgumentResolvers()를 추가한다.
- 다른 HandlerMethodArgumentResolver가 필요한 경우 같은 방식으로 추가한다.
@RequiredArgsConstructor
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final LoginUserArgumentResolver loginUserArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolver) {
argumentResolver.add(loginUserArgumentResolver);
}
}
Controller 수정
- 세션을 사용하는 부분 수정
- @LoginUser를 파라미터로 받아 사용할 수 있도록 수정
- @LoginUser SessionUser user
- 기존 (SessionUser) httpSession.getAttribute("user")로 가져오던 세션 정보 값을 개선
- 다른 컨트롤러에서 세션이 필요한 경우 @LoginUser를 사용하여 세션 정보를 가져올 수 있다.
@RequiredArgsConstructor
@Controller
public class IndexController {
private final PostsService postsService;
private final HttpSession httpSession;
@GetMapping("/")
public String index(Model model, @LoginUser SessionUser user) {
model.addAttribute("posts", postsService.findAllDesc());
if(user != null) {
model.addAttribute("userName", user.getName());
}
return "index";
}
@GetMapping("/posts/save")
public String postsSave() {
return "posts-save";
}
@GetMapping("/posts/update/{id}")
public String postsUpdate(@PathVariable Long id, Model model) {
PostsResponseDto dto = postsService.findById(id);
model.addAttribute("post", dto);
return "posts-update";
}
}