В Spring MVC есть возможность создавать цепочки объектов ViewResolver. Таким образом, обработка разных запросов может осуществлятся разными ViewResolver'ами и, соответственно, возвращаемый результат может быть абсолютно разным.
Рассмотрим следующий задачу: необходимо чтобы на все запросы от клиента возвращался ответ в виде HTML-страницы, кроме одного запроса /plaintext-view - ответ на него должен быть обычным текстом без заголовков, которые присущи HTML-страницам.
Решим эту задачу, воспользовавшись разными стандартными ViewResolver'ами: InternalResourceViewResolver (для HTML-страниц) и XmlViewResolver (для текста).
Для начала необходимо изменить конфигурацию контекста сервлета. Добавьте следующие ViewResolver'ы в файл конфигурации:
<beans:bean class="org.springframework.web.servlet.view.XmlViewResolver">
<beans:property name="order" value="1" />
<beans:property name="location" value="/WEB-INF/views.xml" />
</beans:bean>
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<beans:property name="order" value="2" />
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
Обратите внимание на свойство order. Благодаря ему XmlViewResolver будет выполнятся первым, затем - InternalResourceViewResolver. Если и в InternalResourceViewResolver запрос не обработается, то сгенерируется исключение ServletException.
Внимание!!! InternalResourceViewResolver должен выполняться ВСЕГДА в последнюю очередь. Иначе это привидет к ошибкам.
Полный файл конфигурации контекста сервлета выглядит следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
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">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<beans:bean class="org.springframework.web.servlet.view.XmlViewResolver">
<beans:property name="order" value="1" />
<beans:property name="location" value="/WEB-INF/views.xml" />
</beans:bean>
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<beans:property name="order" value="2" />
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.seostella.spring" />
</beans:beans>
XmlViewResolver в свойстве location сообщает местоположение конфигурационного файла. В нашем случае - /WEB-INF/views.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
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">
<beans:bean name="plainTextView" class="com.seostella.spring.PlainTextView" />
</beans:beans>
В нашем примере только один bean под именем plainTextView. На самом деле их может быть сколь угодно много. Обратите внимание, что имя будет использоваться контроллером в качестве имени представления.
Представление выглядит следующим образом:
package com.seostella.spring;
import java.io.PrintWriter;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.view.AbstractView;
public class PlainTextView extends AbstractView{
@Override
protected void renderMergedOutputModel(Map<String, Object> model,
HttpServletRequest request, HttpServletResponse response) throws Exception {
PrintWriter writer = response.getWriter();
writer.write("Hi from PlainTextView");
writer.close();
}
}
Как видно, в поток ответа записывается обычный текст "Hi from PlainTextView".
И, наконец, контроллер выглядит так:
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
return "home";
}
@RequestMapping(value = "/plaintext-view", method = RequestMethod.GET)
public String customView() {
return "plainTextView";
}
Если имя представления, которое возвращает контроллер, совпадает с одним из bean'ов в файле /WEB-INF/views.xml, то будет использоваться XmlViewResolver, в другом случае - InternalResourceViewResolver. То есть, в этом примере для метода home используется InternalResourceViewResolver, а для метода customView - XmlViewResolver.
Скачать исходный код проекта, демонстрирующего работу цепочки объектов ViewResolver, Вы можете по следующие ссылке - Скачать spring-viewresolver.zip