'Framework/Spring'에 해당되는 글 1건

  1. 2010.06.01 Spring에서 중첩 파라미터에 대한 Command 처리
Framework/Spring2010. 6. 1. 18:04

Spring과 Struts2 둘다 사용해봤으면 Request Parameter를 Command에 매핑하는 과정에서의 차이점을 알 수 있다.
당연 중첩 파라미터에 대해 기본적으로 처리해주는 Struts2가 사용하기 편리하다.
그러나 Spring에서도 기본적으로 처리가 되지 않는 것은 아니다. 단, 중첩 파라미터의 인스턴스가 미리 생성이 되어 있지 않으면 NullPointException을 발생시킨다는 부분만 없으면 말이다.
그래서 MultiActionController의 소스를 열어서 중첩 파라미터의 인스턴스를 필요에 따라 미리 생성해주는 부분을 추가하여 해결해 보았다. (현재 잘 사용중이다.)

소스를 조금만 파악하면 의외로 아주 간단하다. 단점은 Spring이 버전업이 되면 다시 확인을 해야한다는 것 ...

중첩 파라미터를 의미하는 값은 주로 사용하는 "."을 사용했다.

private final String OVERLAP_PROPERTY_PREFIX = ".";

그리고 실질 적으로 중첩 파라미터를 확인하고 해당 Command의 중첩 인스턴스를 생성해 주는 함수를 추가한다.

protected void preOverlapProperty(HttpServletRequest request, Object command) {
    String paramName = null;
    Enumeration<String> enumer = request.getParameterNames();
    while (enumer.hasMoreElements()) {
        paramName = enumer.nextElement();

        if (paramName.indexOf(OVERLAP_PROPERTY_PREFIX) != -1) {
            initOverlapProperty(paramName, command);
        }
    }
}


protected Object initOverlapProperty(String propertyName, Object bean) {
    StringTokenizer st = new StringTokenizer(propertyName, OVERLAP_PROPERTY_PREFIX);
    String subPropertyName = null;
    Object beanObject = bean;
    BeanMap beanMap = new BeanMap(beanObject);

    while (st.hasMoreTokens() && st.countTokens() > 1) {
        subPropertyName = st.nextToken();
        beanObject = beanMap.get(subPropertyName);

        if (beanObject == null) {
            Class subBeanClass = beanMap.getType(subPropertyName);
            if (subBeanClass != null) {
                try {
                    beanObject = subBeanClass.newInstance();
                    beanMap.put(subPropertyName, beanObject);
                    beanMap = new BeanMap(beanObject);
                } catch (Exception e) { }
            }
        }
    }
    return bean;
}


그럼 이렇게 중첩 파라미터에 대한 처리를 해주는 추가 된 함수를 어디에서 호출을 해야되나 ...
원래 MultiActionController 클래스의 invokeNamedMethod 함수 내에서 bind 하기 전에 preOverlapProperty 함수를 호출하면 된다.
수정 된 소스는 아래와 같다.

protected final ModelAndView invokeNamedMethod(String methodName,
        HttpServletRequest request, HttpServletResponse response)
        throws Exception {

    Method method = (Method) this.handlerMethodMap.get(methodName);
        ...

    params.add(command);
    
    preOverlapProperty(request, command); // 중첩 파라미터 처리를 위해 추가 된 부분

    bind(request, command);
        ...
}

위와 같이 하면 Struts2에서 사용하는 중첩 파라미터에 대해서 동일하게 처리가 된다.
뭐 수정 된 부분은 원 Spring의 파라미터 binding을 하는 로직은 그대로 사용을 하며, 단지 Command 내에 선언 된 객체에 대해 Request Parameter에서 필요하다면 미리 Instance를 생성해주어 NullPointException의 발생을 피한 것 밖에 없다.

첨부한 소스는 현재 서비스에서 사용하고 있는 Base Control이며 위의 중첩 파라미터의 처리 외에 Request와 Response 그리고 Model에 대한 선/후 간단한 Logging이 추가되어 있는 소스이다.

Posted by as.wind.914