본문 바로가기
카테고리 없음

아규먼트 리졸버(Argument Resolver)

by am6:00 2019. 9. 4.

아규먼트 리졸버(Argument Resolver)

컨트롤러의 메소드의 인자로 사용자가 임의의 값을 전달하는 방법을 제공할때 사용합니다.예를들어, 세션에 저장되어 있는 값 중 특정이름의 값을 메소드 인자로 전달할때 사용합니다.

 

아규먼트 리졸버 작성방법

1. org.springframework.web.method.support.HandlerMethodArgumentResolver를 구현한 클래스를 작성
2. supportsParameter메소드를 오버라이딩 한 후, 원하는 타입의 인자가 있는지 검사한 후 있을 경우 true가 리턴
3. resolveArgument메소드를 오버라이딩 한 후, 메소드의 인자로 전달할 값을 리턴

 

 

아규먼트 리졸버 설정방법

1 )Java Config에 설정

WebMvcConfigurerAdapter를 상속받은 Java Config 파일에서 addArgumentResolvers 메소드를 오버라이딩 한 후 원하는 아규먼트 리졸버 클래스 객체를 등록

2)xml 파일에 설정

 <mvc:annotation-driven>
        <mvc:argument-resolvers>
            <bean class="아규먼트리졸버클래스"></bean>      
        </mvc:argument-resolvers>
    </mvc:annotation-driven>

 

 

Spring MVC의 기본 ArgumentResolver들

getDefaultArgumentResolvers()메소드를 보면 기본으로 설정되는 아규먼트 리졸버에 어떤 것이 있는지 알 수 있습니다. Map객체나 Map을 상속받은 객체는 Spring에서 이미 선언한 아규먼트 리졸버가 처리하기 때문에 전달 할 수 없습니다. Map객체를 전달하려면 Map을 필드로 가지고 있는 별도의 객체를 선언한 후 사용해야 합니다.

 


 

HTTP Header정보를 Map객체에 담아서 Controller에게 전달하기

아규먼트 리졸버를 적용해서 HTTP 요청 헤더 정보를 저장하고 있는 HeaderInfo 인자 타입이 메서드에 있을 경우에 자동으로 넘겨주는 예제입니다.

 

Map이나 Map을 상속받고 있는 객체는 스프링에서 내부적으로 사용하고 있는 아규먼트 리졸버가 선처리하기 때문에 직접사용할수 없습니다. 그래서 Map 을 필드로 가지고 있는 HeaderInfo 라는 클래스를 새로 작성해 아규먼트 리졸버에서 사용하도록 해야합니다. put(), get()메소드를 이용해 값을 넣고 꺼낼수 있도록 합니다.

 

HeaderInfo.java

import java.util.HashMap;
import java.util.Map;

public class HeaderInfo {
	private Map<String, String> map;
	
	public HeaderInfo() {
		map = new HashMap<>();
	}

	public void put(String name, String value) {
		map.put(name,  value);
	}
	
	public String get(String name) {
		return map.get(name);
	}

}

 

HeaderMapArgumentResolver.java

import java.util.Iterator;

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;

public class HeaderMapArgumentResolver implements HandlerMethodArgumentResolver {

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return parameter.getParameterType() == HeaderInfo.class;
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    	HeaderInfo headerInfo = new HeaderInfo();
		Iterator<String> headerNames = webRequest.getHeaderNames();
		while(headerNames.hasNext()) {
			String headerName = headerNames.next();
			String headerValue = webRequest.getHeader(headerName);
			headerInfo.put(headerName, headerValue);
		}
		return headerInfo;
	}
}

supportsParameter()

해당 파라미터 정보에 원하는 정보가 있다면 true를 반환 아니면 false 반환합니다. 위에서 만든 HeaderInfo 라는 클래스 타입이 인자로 넘어올 경우에 true 를 리턴 하도록 메서드를 오버라이드 하였고, supportsParameter가 true 를 리턴할 경우에만 resolveArgument 메서드가 호출됩니다.

 

resolveArgument()

supportsParameter() 메소드가 true 를 리턴할 경우에만 resolveArgument 메서드가 호출되고, 이 resolveArgument 가 리턴한 값은 Controller 메서드의 파라미터로 전달됩니다.

헤더에 들어있는 정보를 꺼내오기 위해 다음과 같은 과정을 거칩니다.

1. HeaderInfo headerInfo 선언
2. NativeWebRequest 로부터 헤더의 name들을 Iterator 형태로 추출.
3. 위에서 추출한것을 while 문 안에서 헤더의 이름과 헤더의 value를 얻어내 headerInfo에다가 put() 메소드를 통해 정보 저장.

 

아규먼트 리졸버 설정

아규먼트 리졸버를 적용하려면 WebMvcConfigurerAdapter를 상속받은 Java Config 파일에 addArgumentResolvers메소드를 오버라이딩 하고, 인자로 넘어온 argumentResolvers에 앞에서 생성한 아규먼트 리졸버를 넘겨줍니다.

 

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
		argumentResolvers.add(new HeaderMapArgumentResolver());
	}

 

아규먼트 리졸버를 컨트롤러에 적용

GuestbookController 의 메소드인 list메소드의 인자로  HeaderInfo headerInfo를 추가합니다.

콘솔에 headerInfo의 get메소드에 user-agent를 넘겨서 값이 잘 출력되는지 확인할 수 있도록 코드를 추가합니다.

@GetMapping(path="/list")
public String list(@RequestParam(name="start", required=false, defaultValue="0") int start, 
	ModelMap model, @CookieValue(value="count", defaultValue="1", required=true) String value, 
	HttpServletResponse response,
	HeaderInfo headerInfo) {
	System.out.println("-----------------------------------------------------");
	System.out.println(headerInfo.get("user-agent"));
	System.out.println("-----------------------------------------------------");

 

 


출처

1. https://www.edwith.org/boostcourse-web/lecture/16806/

 

[LECTURE] 1) 아규먼트 리졸버란? : edwith

들어가기 전에 이번 시간엔 컨트롤러의 메소드의 인자값으로 사용자가 임의의 값을 전달할 수 있도록 도와주는 아규먼트 리졸버(Argument Resolver)에 대해 알아보도록 하겠습... - 부스트코스

www.edwith.org