ContentNegotiatingViewResolver 활용 : 하나의 RequestMapping 으로 JSP, JSON, JSONP 처리하기
Spring 2011. 8. 19. 19:28
뭔가를 맨들다 보면 데이터를 가져와서 대부분 JSP 를 이용해서 랜더링을 하게 되지만 똑같은 데이터를 ajax 호출을 통해 json 형식으로 받고 싶은 경우도 종종 있다.
그리고 JSONP 형식으로 같은 도메인이 아닌 다른 도메인으로 데이터를 제공하고 싶은 경우도 있다.
고럴때 ContentNegotiatingViewResolver 를 활용하면 하나의 리퀘스트 핸들러를 맹글어 놓고 맨 뒤에 URL 만 살짝 바꾸면 URL 에 따라 다른 View 를 이용해서 랜더링 시킬 수 있다.
예를 들어
http://127.0.0.1:8080/test/view 요럴땐 jsp 로 랜더링
http://127.0.0.1:8080/test/view.json 요럴땐 json 형식으로 랜더링
http://127.0.0.1:8080/test/view.jsonp 요럴땐 jsonp 형식으로 랜더링~
또 약간의 노력을 더해주면 xml 형식이나 rss 형식으로도 랜더링 시킬 수 있다.
죠런 기능을 구현하기 위해서 ContentNegotiatingViewResolver 를 사용하도록 설정해 주고 필요에 따라 AbstractView 클래스를 구현해서 원하는 View를 맹글면 된다.
스프링 설정파일
stove99.views.JSONPView 클래스 소스
컨트롤러 소스
테스트 결과 화면
그리고 JSONP 형식으로 같은 도메인이 아닌 다른 도메인으로 데이터를 제공하고 싶은 경우도 있다.
고럴때 ContentNegotiatingViewResolver 를 활용하면 하나의 리퀘스트 핸들러를 맹글어 놓고 맨 뒤에 URL 만 살짝 바꾸면 URL 에 따라 다른 View 를 이용해서 랜더링 시킬 수 있다.
예를 들어
http://127.0.0.1:8080/test/view 요럴땐 jsp 로 랜더링
http://127.0.0.1:8080/test/view.json 요럴땐 json 형식으로 랜더링
http://127.0.0.1:8080/test/view.jsonp 요럴땐 jsonp 형식으로 랜더링~
또 약간의 노력을 더해주면 xml 형식이나 rss 형식으로도 랜더링 시킬 수 있다.
죠런 기능을 구현하기 위해서 ContentNegotiatingViewResolver 를 사용하도록 설정해 주고 필요에 따라 AbstractView 클래스를 구현해서 원하는 View를 맹글면 된다.
스프링 설정파일
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <!-- ViewResolver 우선순위 설정 --> <property name="order" value="1" /> <property name="mediaTypes"> <!-- 맵핑될 확장자 정의 --> <map> <entry key="json" value="application/json" /> <entry key="jsonp" value="javascript/jsonp" /> </map> </property> <property name="defaultViews"> <list> <!-- JSON 요청을 처리할 뷰 --> <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/> <!-- JSONP 요청을 처리할 뷰 --> <bean class="stove99.views.JSONPView"> <property name="contentType" value="javascript/jsonp"/> </bean> </list> </property> <property name="ignoreAcceptHeader" value="true" /> </bean> <!-- 맵핑되는 확장자가 없을때 JSP 로 뷰 처리 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="order" value="2" /> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean>mediaTypes에 정의된 entry 들은 URL 맨 뒤에 붙은 확장자와 mediaType 을 설정한다. 여기에서 설정된 mediaType 정보를 바탕으로 아래쪽 defaultViews 목록에 정의된 View 들 중에서 랜더링 가능한 View 를 찾아서 그 View 로 랜더링 시킨다. 뭐 설명이 허접하긴 하지만 내가 이해한 바로는 그렇다.
stove99.views.JSONPView 클래스 소스
package stove99.views; import java.io.Writer; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.codehaus.jackson.map.ObjectMapper; import org.springframework.web.servlet.view.AbstractView; public class JSONPView extends AbstractView{ @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { String callback = request.getParameter("callback"); ObjectMapper om = new ObjectMapper(); String json = om.writeValueAsString(model); Writer out = response.getWriter(); out.append(callback).append("(").append(json).append(")"); } }
컨트롤러 소스
package stove99.controller; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/test/*") public class TestController { @RequestMapping public void view(ModelMap model) { Map<String, String> data = new HashMap<String, String>(); data.put("data1", "value1"); data.put("data2", "value2"); data.put("data3", "value3"); model.addAttribute("model", data); } }
테스트 결과 화면
ContentNegotiatingViewResolverTest.war
'Spring' 카테고리의 다른 글
Spring @ResponseBody 로 리턴시 한글이 깨질때 (0) | 2013.04.16 |
---|---|
<util:properties/> 와 Spring EL 로 값 가져오기 (0) | 2013.04.12 |
Spring 개발시 개발, 운영환경 프로퍼티 파일 관리하기 (1) | 2011.10.11 |
bean property 간단하게 설정하기 : http://www.springframework.org/schema/p 활용 (1) | 2011.08.22 |
<context:property-placeholder/> 를 사용할때 property file의 encoding 지정하기 (0) | 2011.08.03 |