HandlerMethodArgumentResolver
Strategy interface for resolving method parameters into argument values in the context of a given request.
컨트롤러에 들어오는 파라미터를 커스터마이징할 때 사용할 수 있는 인터페이스로, 공통적으로 수행해야 하는 작업을 수행한 후 해당 Object를 반환함으로써 코드의 중복을 줄일 수 있다. 클라이언트의 요청이 담긴 파라미터를 컨트롤러보다 먼저 받아서 작업을 수행한다.
Instance Method | Description |
---|---|
Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,WebDataBinderFactory binderFactory) | 공통작업 수행 후 리턴 |
boolean supportsParameter(MethodParameter parameter) | parameter가 해당 resolver에 의해 수행될 수 있는 타입인지 true/false로 리턴. 이 메소드가 먼저 수행되고 true일 시 resolveArgument를 수행한다. |
예제
-
User 타입의 파라미터를 통해 사용자가 접속한다.
-
User 아이디는 a, b, c 셋 중 하나로 시작한다.
-
a 로 시작하면 관리자, b로 시작하면 vip회원, c로 시작하면 일반회원이다.
-
각 사용자별로 페이지에 접속할 수 있는 권한이 차등지급된다.
-
본인이 접속할 수 없는 페이지면 상태코드 403(FORBIDDEN)을 리턴한다.
1) User 객체생성
package com.edu.tistory.model;
import lombok.Getter;
import lombok.Setter;
@Getter
public class User {
private String userId;
private String userPassword;
@Setter
private UserType userType;
public enum UserType {
Manager, VIPMember, Member
}
}
2) LoginUser 어노테이션 생성
package com.edu.tistory.custom;
import java.lang.annotation.Documented;
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)
@Documented
public @interface LoginUser {
}
3) HandlerMethodArgumentResolver 구현
package com.edu.tistory.custom;
import org.springframework.core.MethodParameter;
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 com.edu.tistory.model.User;
import com.edu.tistory.model.User.UserType;
public class LoginUserResolver implements HandlerMethodArgumentResolver{
@Override
public boolean supportsParameter(MethodParameter parameter) {
//parameter가 User Type인지 체크
return parameter.getParameterType().isAssignableFrom(User.class)
&& parameter.hasParameterAnnotation(LoginUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
User user = new User();
//User의 id가 시작하는 값에 따라 UserType(Manager, VIPMemeber, Member)차등부여하고 리턴
String userId= webRequest.getParameter("userId");
if(userId.charAt(0) == 'a') user.setUserType(UserType.Manager);
else if(userId.charAt(0)=='b') user.setUserType(UserType.VIPMember);
else user.setUserType(UserType.Member);
return user;
}
}
4) Controller 구현
package com.edu.tistory.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.edu.tistory.custom.LoginUser;
import com.edu.tistory.model.User;
import com.edu.tistory.model.User.UserType;
@RestController
public class LoginController {
@GetMapping("/login/manager")
public ResponseEntity<String> pageForManager(@LoginUser User user) {
// Page for manager
return getResponseEntity(user, UserType.Manager);
}
@GetMapping("/login/vip")
public ResponseEntity<String> pageForVIPMember(@LoginUser User user) {
// Page for vip
return getResponseEntity(user, UserType.VIPMember);
}
@GetMapping("/login/member")
public ResponseEntity<String> pageForMember(@LoginUser User user) {
// Page for member
return getResponseEntity(user,UserType.Member);
}
public ResponseEntity<String> getResponseEntity(User user, UserType userType) {
if(user.getUserType()!=userType)
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
return new ResponseEntity<String>(HttpStatus.OK);
}
}
5) Config 작성
package com.edu.tistory.config;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.edu.tistory.custom.LoginUserResolver;
@Configuration
public class WebConfig implements WebMvcConfigurer{
@Bean
public LoginUserResolver loginUserResolver() {
return new LoginUserResolver();
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(loginUserResolver());
WebMvcConfigurer.super.addArgumentResolvers(resolvers);
}
}
위와 같이 작성 후 userId 에 차이를 주고 url에 접근하면 적절히 resolver가 수행되는 것을 알 수 있다.
소스코드: https://github.com/csbsjy/spring-study-example/tree/master/spring-handler-method-argument-resolver
헷갈리는 아래 개념 정리는 다음 ㅇ ㅣ 시간에 ,,
Interceptor vs HandlerMethodArgument vs Model
'개발 > Java & Spring ' 카테고리의 다른 글
[Spring boot - webpack] Webpack으로 js파일 모듈화하고 번들링하기 (0) | 2019.07.14 |
---|---|
[Spring boot] 하나의 클래스로 properties 관리하여 사용하기! (0) | 2019.05.13 |
[Spring/SpringBoot] RestTemplate으로 HTTP 요청 후 응답받기 (1) | 2019.02.26 |
[Java] JNI로 c 소스파일 불러오기 (0) | 2018.11.21 |
[JAVA8] java 8 ZonedDateTime 을 Oracle timestamp 로 변환하기 (0) | 2018.10.26 |