일반적으로 Ajax와 함께 웹 애플리케이션을 개발하게 될 경우 XML을 응답으로 주어야 할 경우가 많다.
또한, Spring framework을 애플리케이션 서버에서 사용할 경우 대부분 Spring MVC를 사용하게 되어 있다.
그렇다면 이 둘의 조합인 Spring MVC에서 XML로 응답하는 방법은 어떨까? 일반적인 Spring MVC의 사이클은 다음의 그림과 같다.

위의 그림에서 살펴보는대로 ViewResolver를 통해서 View 객체(또는 String)을 결정하게 되어 최종 View를 처리해 주어야 한다.
보통은 다음과 같이 InternalResourceViewResolver를 사용하여 jsp 파일을 view를 담당하게 된다.
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
문제는 이러한 일반적인 상황이 아닌, Spring MVC를 사용하여 XML로 응답하고 싶은 경우이다. Spring MVC를 사용하지 않고, 기존의 방식을 따라서 Servlet에서 처리해 주면 되는데 Servlet을 사용할 경우 매번 web.xml에 Servlet 관련 셋팅을 해 주어야 하고, Spring DAO, Interface 같은 Content Loader를 항상 해 주어야 하는 번거러움이 있다.
그리고, Spring MVC를 사용하는 것이 Request의 처리나 비지니스 로직에 집중하기가 쉬움으로 XML을 응답으로 주어야 할 다른 경우에도 Spring MVC 내에서 XML을 응답해 주는 방법이 필요하다.
방법은 이미 Spring framework 에서 ViewResolver 중에 결정해 두었다. 다음의 XmlViewResolver 셋팅을 보자.
<!-- XML View Resolver -->
<bean id="xmlViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="order" value="1"/>
<property name="location" value="/WEB-INF/config/xml-views.xml"/>
</bean>
xmlViewResolver id명으로 "org.springframework.web.servlet.view.XmlViewResolver" 클래스를 사용하고 있다. 그리고 location property의 값으로 다른 XML 설정 파일을 지정하고 있다. 그러면 xml-views.xml을 살펴보자.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--
ajax view a single xml rendering
-->
<bean name="ajaxResponseXMLView" class="net.wiseant.web.xml.AjaxResponseXMLView">
<property name="contentType">
<value>text/xml;charset=utf-8</value>
</property>
</bean>
</beans>
간단하게 하나의 클래스만 ajaxResponseXMLView라는 id명으로 정의하고 있다. XML 응답을 최종 AjaxResponseXMLView 클래스를 통해서 해 준다는 말이다. 간단하게 이 클래스를 살펴보자.
public class AjaxResponseXMLView extends AbstractView {
private final Logger logger = Logger.getLogger(getClass());
/* (non-Javadoc)
* @see org.springframework.web.servlet.view.AbstractView#renderMergedOutputModel(java.util.Map, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void renderMergedOutputModel(Map map, HttpServletRequest request,
HttpServletResponse response) throws Exception {
// TODO Auto-generated method stub
String xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
StringBuffer xmlSb = new StringBuffer();
sb.append(xmlHeader);
sb.append(/*XML 내용 */);
response.setContentType("application/xml");
response.setCharacterEncoding("utf-8");
response.setHeader("Cache-Control", "no-cache");
response.setContentLength(xmlSb.toString().getBytes("utf-8").length);
response.getWriter().print(xmlSb.toString());
}
}
AbstractView 추상 클래스를 extends하여 구현한 클래스이다. 위의 예제에서는 XML 내용이 포함되어 있지 않다. 프로젝트에 필요한 XML을 넣어주면 된다.
이렇게 하면 AjaxResponseXMLView 클래스를 통해서 XML을 응답으로 처리해 줄 수 있다. 그렇다면 요청은?
요청시에는 Spring framework 버전에 따라서 다를 수가 있는데 이번 예제에서는 Spring2.5 기준으로 한 Annotation 기반의 예제를 사용한다.
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* @author Sang Hyup Lee
* @version 1.0
*
*/
@Controller
public class AjaxRequestController {
private final Logger logger = Logger.getLogger(getClass());
private String xmlView = "ajaxResponseXMLView";
/**
* @param categoryService the categoryService to set
*/
@Autowired
public void setCategoryService(CategoryService categoryService) {
this.categoryService = categoryService;
}
/**
* @param xmlView the xmlView to set
*/
/*
@Autowired
public void setAjaxResponseXMLView(AjaxResponseXMLView ajaxResponseXMLView) {
this.ajaxResponseXMLView = ajaxResponseXMLView;
}
*/
@RequestMapping(value="/ajax/contentDirectory")
public ModelAndView contentDirectory(HttpServletRequest request,
HttpServletResponse response, ModelMap model) {
logger.debug("/ajax/contentDirectory.do Request process");
// Request process
return new ModelAndView(xmlView);
}
}
살펴볼 부분은 리턴 타입이 ModelAndView인데 보통 Spring MVC Controller를 확장하여 사용할 경우와 동일하다. 이 때 간단하게 String 타입의 id 명을 그러니깐 이전에 셋팅해 준 ajaxResponseXMLView 클래스를 지정한 ID를 명시해 주었다.
그러면 최종 리턴 객체를 AjaxResponseXMLView 클래스를 사용하여 XML를 리턴하게 된다.
댓글 없음:
댓글 쓰기