В 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