'Customize'에 해당되는 글 1건

  1. 커스텀 ReturnValueHandler 등록하기

커스텀 ReturnValueHandler 등록하기

개요

이전에는 컨트롤러에 들어오는 파라미터를 가공하는 방법에 대해 알아보았는데, 이번에는 반대로 리턴타입을 기준으로 분기할 수 있는 ReturnValueHandler를 구현해보려 한다. 기존에는 ModelAndViewResolver를 구현해서 AnnotationMethodHandlerAdapter에 등록을 해야 했는데, 스프링 3.2버전 부터는 deprecated 된 상태다. 지금은 ModelAndViewResolver는 남아 있기는 하나 앞으로 HandlerMethodReturnValueHandler 사용하기를 권하고 있다. 모든 HandlerMethodReturnValueHandler를 검색해봐도 리턴된 클래스를 처리 하는 핸들러를 못 찾을 경우에만 ModelAndViewResolver를 검색하기 시작한다.

예제

이전에 파라미터를 Map 형태로 수집하는 클래스를 만들었는데, 이번에는 그 안에 내용에 따라 view를 분기 시켜보려 한다. 파라미터 수집하는 예제는 (http://jekalmin.tistory.com/entry/%EC%BB%A4%EC%8A%A4%ED%85%80-ArgumentResolver-%EB%93%B1%EB%A1%9D%ED%95%98%EA%B8%B0) 이 글을 참고하길 바란다. 먼저 HandlerMethodReturnValueHandler를 구현한 클래스를 생성하고 dispatcherServlet에 등록해주자.


ParamCollectorReturnValueHandler.java

package com.tistory.jekalmin;

import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

public class ParamCollectorReturnValueHandler implements HandlerMethodReturnValueHandler {

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        // TODO Auto-generated method stub
        return ParamCollector.class.isAssignableFrom(returnType.getParameterType());
    }

    @Override
    public void handleReturnValue(Object returnValue,
            MethodParameter returnType, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest) throws Exception {
        // TODO Auto-generated method stub
        ParamCollector collector = (ParamCollector)returnValue;
        if(collector.get("viewType").equals("json")){
            // json View 등록
            System.out.println("json View 등록하는 곳");
        }
    }

}

다음 dispatcherServlet의 설정이다.


mvc-config.xml

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

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

    <context:component-scan base-package="com.tistory.jekalmin"/>


    <mvc:annotation-driven>
        <mvc:argument-resolvers>
            <bean class="com.tistory.jekalmin.ParamCollectorArgumentResolver"></bean>
        </mvc:argument-resolvers>
        <mvc:return-value-handlers>
            <bean class="com.tistory.jekalmin.ParamCollectorReturnValueHandler"></bean>
        </mvc:return-value-handlers>
    </mvc:annotation-driven>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!-- Example: a logical view name of 'showMessage' is mapped to '/WEB-INF/jsp/showMessage.jsp' -->
            <property name="prefix" value="/WEB-INF/view/"/>
            <property name="suffix" value=".jsp"/>
    </bean>

</beans>

마지막으로 TestController 이다.


TestController.java

package com.tistory.jekalmin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test")
public class TestController {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    @RequestMapping("/index")
    public ParamCollector index(ParamCollector collector){
        System.out.println(collector);
        return collector;
    }
}


http://localhost:8080/test/index?viewType=json 일때만 아래 글이 출력되는 것을 확인할 수 있다.

json View 등록하는 곳

결론

HandlerMethodReturnValueHandler를 구현하면 리턴타입이나 리턴된 데이터에 따라서 내가 원하는 view로 보낼 수 있다. 그 View는 흔히 사용하는 JstlView가 될 수도 있지만, AbstractView 등을 구현하여 커스터마이징 해서 사용할 수도 있다.