[Spring] HandlerMethodArgumentResolver를 구현한 세 가지 Argument Resolver 확인해보기(@PathVariable, @RequestParam, @RequestHeader)

GilLog·2021년 7월 23일
0

Spring

목록 보기
17/22

🙆‍♂️ import 🙇‍♂️

Custom HandlerMethodArgumentResolver 만들어보기[Advenoh - FRANK OH]

Spring Argument Resovler[jaehun2841.github.io]


Spring에서 구현된 HandlerMethodArgumentResolver


지금까지 많이 사용했던 @PathVariable, @RequestParam, @RequestHeader Annotation도,

HandlerMethodArgumentResolverSpring에서 구현Resolver에서 사용하게되는 Annotation이다.


Spring에서 HandlerMethodArgumentHandler를 구현한 Resolver로는 아래 세 가지,

PathVariableMethodArgumentResolver, RequestParamMethodArgumentResolver, RequestHeaderMapMethodArgumentResolver가 있다.


PathVariableMethodArgumentResolver

PathVariableMethodArgumentResolverHandlerMethodArgumentHandler Interfaceimplements한,

AbstractNamedValueMethodArgumentResolver Abstract class상속한 Resolver이다.

PathVariableMethodArgumentResolverController Argument,

@PathVariable이 앞에 선언된 Argument처리하는 Argument Resolver이다.

@GetMapping("/gillog/{id}")
public ResponseEntity<String> getGillog(@PathVariable(name = "id") String id) {
	return ResponseEntity.ok().body(id);
}

PathVariableMethodArgumentResolversupportsParameter method 부분을 살펴보면,

parameter의 AnnotationPathVariable인지를 체크하여, 해당 Resolver에서 처리 여부를 결정한다.

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		if (!parameter.hasParameterAnnotation(PathVariable.class)) {
			return false;
		}
		if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
			String paramName = parameter.getParameterAnnotation(PathVariable.class).value();
			return StringUtils.hasText(paramName);
		}
		return true;
	}

위와 같이 @PathVariable과 사용되는 Argument를 처리하는 Resolver이고,

Spring에서 구현한 @PathVariable Annotation은 아래와 같은 형태이다.

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PathVariable {

	/**
	 * Alias for {@link #name}.
	 */
	@AliasFor("name")
	String value() default "";

	/**
	 * The name of the path variable to bind to.
	 * @since 4.3.3
	 */
	@AliasFor("value")
	String name() default "";

	/**
	 * Whether the path variable is required.
	 * <p>Defaults to {@code true}, leading to an exception being thrown if the path
	 * variable is missing in the incoming request. Switch this to {@code false} if
	 * you prefer a {@code null} or Java 8 {@code java.util.Optional} in this case.
	 * e.g. on a {@code ModelAttribute} method which serves for different requests.
	 * @since 4.3.3
	 */
	boolean required() default true;

}

RequestParamMethodArgumentResolver

RequestParamMethodArgumentResolverHandlerMethodArgumentHandler Interfaceimplements한,

AbstractNamedValueMethodArgumentResolver Abstract class상속한 Resolver이다.

RequestParamMethodArgumentResolverController Argument,

@RequestParam이 앞에 선언된 Argument처리하는 Argument Resolver이다.

@GetMapping("/gillog")
public ResponseEntity<String> getGillog(@RequestParam(name = "id") String id) {
	return ResponseEntity.ok().body(id);
}

RequestParamMethodArgumentResolversupportsParameter method 부분을 살펴보면,

parameter의 Annotation이 RequestParam인지를 체크하여 해당 Resolver에서 처리할지 결정한다.

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		if (parameter.hasParameterAnnotation(RequestParam.class)) {
			if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
				String paramName = parameter.getParameterAnnotation(RequestParam.class).name();
				return StringUtils.hasText(paramName);
			}
			else {
				return true;
			}
		}
		else {
			if (parameter.hasParameterAnnotation(RequestPart.class)) {
				return false;
			}
			parameter = parameter.nestedIfOptional();
			if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
				return true;
			}
			else if (this.useDefaultResolution) {
				return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());
			}
			else {
				return false;
			}
		}
	}

위와 같이 @RequestParam과 사용되는 Argument를 처리하는 Resolver이고,

Spring에서 구현한 @RequestParam Annotation은 아래와 같은 형태이다.

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {

	/**
	 * Alias for {@link #name}.
	 */
	@AliasFor("name")
	String value() default "";

	/**
	 * The name of the request parameter to bind to.
	 * @since 4.2
	 */
	@AliasFor("value")
	String name() default "";

	/**
	 * Whether the parameter is required.
	 * <p>Defaults to {@code true}, leading to an exception being thrown
	 * if the parameter is missing in the request. Switch this to
	 * {@code false} if you prefer a {@code null} value if the parameter is
	 * not present in the request.
	 * <p>Alternatively, provide a {@link #defaultValue}, which implicitly
	 * sets this flag to {@code false}.
	 */
	boolean required() default true;

	/**
	 * The default value to use as a fallback when the request parameter is
	 * not provided or has an empty value.
	 * <p>Supplying a default value implicitly sets {@link #required} to
	 * {@code false}.
	 */
	String defaultValue() default ValueConstants.DEFAULT_NONE;

}

RequestHeaderMapMethodArgumentResolver

RequestHeaderMapMethodArgumentResolverHandlerMethodArgumentHandler InterfaceimplementsResolver이다.

RequestHeaderMapMethodArgumentResolverController Argument,

@RequestHeader가 앞에 선언된 Argument처리하는 Argument Resolver이다.

@GetMapping("/gillog")
public ResponseEntity<String> getGillog(@RequestHeader(name = "Authorization") String jwt) {
	return ResponseEntity.ok().body(jwt);
}

RequestHeaderMapMethodArgumentResolversupportsParameter method 부분을 살펴보면,

parameter의 Annotation이 RequestHeader인지를 체크하여 해당 Resolver에서 처리할지 결정한다.

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return (parameter.hasParameterAnnotation(RequestHeader.class) &&
				Map.class.isAssignableFrom(parameter.getParameterType()));
	}

위와 같이 @RequestHeader와 사용되는 Argument를 처리하는 Resolver이고,

Spring에서 구현한 RequestHeader Annotation은 아래와 같다.

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestHeader {

	/**
	 * Alias for {@link #name}.
	 */
	@AliasFor("name")
	String value() default "";

	/**
	 * The name of the request header to bind to.
	 * @since 4.2
	 */
	@AliasFor("value")
	String name() default "";

	/**
	 * Whether the header is required.
	 * <p>Defaults to {@code true}, leading to an exception being thrown
	 * if the header is missing in the request. Switch this to
	 * {@code false} if you prefer a {@code null} value if the header is
	 * not present in the request.
	 * <p>Alternatively, provide a {@link #defaultValue}, which implicitly
	 * sets this flag to {@code false}.
	 */
	boolean required() default true;

	/**
	 * The default value to use as a fallback.
	 * <p>Supplying a default value implicitly sets {@link #required} to
	 * {@code false}.
	 */
	String defaultValue() default ValueConstants.DEFAULT_NONE;

}
profile
🚀 기록보단 길록을 20.10 ~ 22.02 ⭐ Move To : https://gil-log.github.io/

0개의 댓글