목차

CommandMapArgumentResolver(@Deprecated)

개요

Controller에서 화면(JSP) 입력값을 받기 위해서 일반적으로 Command(Form Class) 객체를 사용하지만, Map 객체를 사용하는걸 선호할 수 있다.
org.springframework.web.bind.support.WebArgumentResolver의 구현클래스인 CommandMapArgumentResolver은 HTTP request 객체에 있는 파라미터이름과 값을 Map 객체에 담아 Controller에서 사용도록 제공한다.

설명

WebArgumentResolver

Sping MVC의 @Controller의 메소드의 argument로 사용할 수 있는 유형(이에 관한 정보는 이곳을 참조하라.)은 기존의 계층형 Controller보다 다양해 졌지만,
필요에 따라 기본 유형외의 custom argument를 사용해야 할때가 있을 것이다.
Sping MVC는 Controller의 argument 유형을 customizing 할 수 있는 WebArgumentResolver라는 interface를 제공한다.

아래와 같이 Controller의 메소드에서 MySpecialArg라는 custom argument를 argument로 사용하려 한다면,

@Controller
public class HelloController{
    public String hello(MySpecialArg mySpecialArg,...){
       ...
       return "...";
    }
}

인터페이스 WebArgumentResolver를 구현한 클래스를 만든다. 구현해야 할 메소드는 아래와 같다.

Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception;
public class MySpecialArgumentResolver implements WebArgumentResolver {
 
   public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) {
     //메소드 argument 유형중에 MySpecialArg.class이 있다면,
     if (methodParameter.getParameterType().equals(MySpecialArg.class)) {
       //new MySpecialArg("myValue")을 값으로 부여한다.
       return new MySpecialArg("myValue");
     }
     return UNRESOLVED;
   }
}

이 WebArgumentResolver의 구현 클래스는 아래의 메소드에서 사용된다.
AnnotationMethodHandlerAdapter.setCustomArgumentResolver(org.springframework.web.bind.support.WebArgumentResolver) - 단수의 WebArgumentResolver
AnnotationMethodHandlerAdapter.setCustomArgumentResolvers(org.springframework.web.bind.support.WebArgumentResolver[]) - 복수의 WebArgumentResolver

따라서, 빈 설정 파일에서 AnnotationMethodHandlerAdapter의 customArgumentResolvers 프로퍼티에 해당 MySpecialArgumentResolver을 등록한다.
list 유형인걸 보면 알겠지만, WebArgumentResolver은 여러개도 등록할수 있다.

	<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="customArgumentResolvers">
			<list>
				<bean class="...MySpecialArgumentResolver"/>
			</list>
		</property>
	</bean>

CommandMapArgumentResolver

HTTP request 객체에 있는 파라미터이름과 값을 특정 폼 빈에 담아서 사용하는 방식이 일반적이지만, Map 객체에 담아서 사용하는걸 선호하는 경우도 있다.
HTTP request 객체의 파라미터를 꺼내서 Map 객체에 담는 작업을 Controller에서 반복적으로 수행하는것 보다는 Interceptor에서 선처리하고 request 객체에서 저장하는게 간편하지만,
아래와 같이 메소드의 파라미터로 전달되는게 더 깔끔하다.

public String helloPost(Map commandMap, ModelMap model) {
...
}

하지만, Map commandMap에 파라미터의 이름과 값이 들어 있게 하려면 위에서 언급한 WebArgumentResolver를 이용해야 한다.
WebArgumentResolver의 구현 클래스인 CommandMapArgumentResolver는
Controller 메소드의 argument중에 commandMap이라는 이름의 Map 객체가 있다면, HTTP request 객체에 있는 파라미터이름과 값을 commandMap Map객체에 담는다.

package egovframework.rte.ptl.mvc.bind;
...
public class CommandMapArgumentResolver implements WebArgumentResolver{
 
	/**
	 * Controller의 메소드 argument에 commandMap이라는 Map 객체가 있다면 
	 * HTTP request 객체에 있는 파라미터이름과 값을 commandMap에 담아 returng한다.
	 * 배열인 파라미터 값은 배열로 Map에 저장한다.
	 */
	public Object resolveArgument(MethodParameter methodParameter,
			NativeWebRequest webRequest) throws Exception {
 
		Class<?> clazz = methodParameter.getParameterType();
		String paramName = methodParameter.getParameterName();
 
		if(clazz.equals(Map.class) && paramName.equals("commandMap")){
 
			Map<String, Object> commandMap = new HashMap<String, Object>();
			HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();			
			Enumeration<?> enumeration = request.getParameterNames();
 
			while(enumeration.hasMoreElements()){
				String key = (String) enumeration.nextElement();
				String[] values = request.getParameterValues(key);
				if(values!=null){
					commandMap.put(key, (values.length > 1) ? values:values[0] );
				}
			}
			return commandMap;
		}
		return UNRESOLVED;
	}
}

CommandMapArgumentResolver를 사용하려면 HandlerAdaptor에 등록해야 한다.

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
	<property name="customArgumentResolvers">
		<list>
			<bean class="egovframework.rte.ptl.mvc.bind.CommandMapArgumentResolver"/>
		</list>
	</property>
</bean>

테스트를 위한 Form에 데이터를 아래와 같이 등록하고 폼을 제출했을때,

commandMap 객체의 데이터는 key, value 형태로 아래와 같이 들어 있다. 같은 파라미터 이름으로 여러값이 들어 있는 값은 배열로 들어 있다.

key:text1   value:{aaa,bbb}
key:text2   value:ccc
key:text3   value:ddd
key:cb   value:{on,on}
key:rb2   value:on
key:rb1   value:on

참고자료