'handlerargumentresolver'에 해당되는 글 1건

  1. 2020.11.25 [Spring] HandlerMethodArgumentResolver 적용
Web&Spring2020. 11. 25. 12:35

 

 

 

아마 이번 포스팅은 스프링에 대한 기본 개념이 있으면 쉽게 이해할 듯 한데..

업무에 이용하기 요긴한 핸들러를 소개하고 싶은 마음에 포스팅.

일단 HandlerMethodArgumentResolver란 스프링 3.1에서 추가된 인터페이스이다.

스프링 3.1 이전은 WebArgumentResolver 였고, 스프링 3.1이후부터 이름이 HandlerMethodArgumentResolve로

변경되었다.

역할은 컨트롤러에 들어오는 파라미터를 수정, 공통 처리를 할 수 있다.

사용자의 요청이 컨트롤러에 도달하기 전에 그 요청의 파라미터들을 수정, 관리할 수 있도록 해주는것이 장점.

보통 CommandMap 객체를 만들어서 잘 쓴다. 다음은 CommandMap의 예제.


1. CommandMap 만들기

 

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

 

public class CommandMap {

    Map<String,Object> map = new HashMap<String,Object>();
    
    public Object get(String key){
        return map.get(key);
    }     

    public void put(String key, Object value){
        map.put(key, value);
    }

    public Object remove(String key){
        return map.remove(key);
    }     

    public boolean containsKey(String key){
        return map.containsKey(key);
    }     

    public boolean containsValue(Object value){
        return map.containsValue(value);
    }     

    public void clear(){
        map.clear();
    }     

    public Set<Entry<String, Object>> entrySet(){
        return map.entrySet();
    }    

    public Set<String> keySet(){
        return map.keySet();
    }     

    public boolean isEmpty(){
        return map.isEmpty();
    }     

    public void putAll(Map<? extends String, ?extends Object> m){
        map.putAll(m);
    }     

    public Map<String,Object> getMap(){
        return map;
    }
}

 

 

그냥 HashMap 가지고 노는 클래스다. 

필요에 따라서 윗단에서 유용하게 쓸 메소드들을 조금 감싸는 정도~


2. HandlerMethodArgumentResolver 만들기!

 

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest; 
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 deerpropect.common.CommandMap; 

public class CustomMapArgumentResolver implements HandlerMethodArgumentResolver{

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

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer 
mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) 
throws Exception {
        CommandMap commandMap = new CommandMap();         
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
        Enumeration<?> enumeration = request.getParameterNames();         

        String key = null;
        String[] values = null;

        while(enumeration.hasMoreElements()){
            key = (String) enumeration.nextElement();
            values = request.getParameterValues(key);
            if(values != null){
                commandMap.put(key, (values.length > 1) ? values:values[0] );
            }
        }

        return commandMap;

    }
}

 

 

HandlerMethodArgumentResolver 인터페이스를 구현하려면 supportsParemeter 메소드와 resolveArgument 

메소드를 반드시 구현해주어야 한다. supportsParameter 메소드는 Resolver가 적용 가능한지 검사하는 역할을 하고,

resolverArgument 메소드는 파라미터 등의 정보를 받아서 실제 객체를 반환한다.

여기서 중요한 부분이 resolveArgument 메소드인데,

request에 담겨있는 키와 값을 iterator로 돌아서 맵에 put put 한다.

그리고 마지막에 반환함~.~

그리고 xml 설정에 미리 등록을 해주면, RequetMapping을 타고 들어온 자바 메소드에서 CommandMap으로 파라미터를

편리하게 받을 수 있다.




그리고 당연히, 빈을 xml에 등록해놔야겠지~

3. xml에 빈 등록

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

...

<mvc:annotation-driven>
        <mvc:argument-resolvers>
            <bean class="first.common.resolver.CustomMapArgumentResolver"></bean>       
        </mvc:argument-resolvers>
    </mvc:annotation-driven>

...

 

 

 

<mvc:argument-resolver> 태그를 써서, 빈을 수동으로 등록해주었다.

4. 확인

Controller에서 앞으로 CommandMap을 받을 수 있다.

 

@RequestMapping(value="/cms/folder/folderDetail.do")
public ModelAndView folderDetail(CommandMap commandMap, HttpServletRequest 
request, HttpServletResponse response) throws Exception{
ModelAndView mav = new ModelAndView("");
if (commandMap.isEmpty() == false) {
     Iterator<Entry<String,Object>> iterator = commandMap.getMap().entrySet().iterator();

        Entry<String,Object> entry = null;
        while(iterator.hasNext()){
            entry = iterator.next();
            System.out.println("key : "+entry.getKey()+", value : "+entry.getValue());
        }
}

return mav;
}

 

 

실제 실무 프로젝트에서도 이 resolver 이용해서 commandMap으로 파라미터 받아서 이용했었고, request 객체를 

타고 넘어오는 파라미터들을 맛깔나게(?) 요리하는데 요긴하게 쓸 수 있음.

 

Posted by 사슴영혼'-'