Spring MVC ViewResolver

Las clases que implementen la interface ViewResolver serán las encargadas de resolver la vista, es decir, obtener el archivo físico que se usará para generar la vistas a partir del nombre lógico devuelto por el controlador, en el Framework Java Spring MVC encontraremos una gran variedad de clases que implementan esta interface, en este tutorial nos enfocaremos en las clases que son usadas para generar vistas JSP, aunque existen implementación que nos permiten trabajar con otras tecnologías de vistas, como: JasperReportsViewResolver diseñada para trabajar con la biblioteca JasperReports, la clase FreeMarkerViewResolver nos permite usar plantillas FreeMarker, entre otras.

Nuestro controlador para este ejemplo:

package carmelo.spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HomeController {

    @RequestMapping("/")
    public ModelAndView homePage() {
        return new ModelAndView("home", "msg", "Usando la interface ViewResolver.");
    }
}

Este controlador asigna home como nombre lógico para la vista, además añadimos un atributo al modelo, lo llamamos msg, para más detalles sobre los controladores puedes ver el tutorial: Spring MVC Controladores.

BeanNameViewResolver

Esta clase resuelve la vista usando el nombre de los bean, esto quiere decir que necesitamos tener un bean llamado home que indique la ubicación del archivo JSP que será usado para generar dicha vista.

Recordemos que el nombre de un bean se puede establecer en la anotación, de esta forma: @Bean(name = "home"), de no hacerlo así, se utilizará el nombre del método con la primera letra en minúscula como nombre del bean.

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"carmelo.spring.controller"})
public class WebAppConfig {

    @Bean
    public ViewResolver viewResolver() {
         return new BeanNameViewResolver();
    }

    @Bean
    public View home() {
        JstlView view = new JstlView();
        view.setUrl("/WEB-INF/views/home.jsp");
        return view;
    }
}

Primero definimos el BeanNameViewResolver y seguido un bean de tipo View que generará la vista, usamos la clase JstlView que genera la vista a partir del archivo JSP indicado, esta clase nos permite usar las etiquetas JSTL.

BeanNameViewResolver Spring MVC

Este es uno de los ViewResolver mas simples que podemos encontrar en el Framework Spring MVC.

XmlViewResolver

Esta clase trabaja de manera similar a la anterior, salvo que los beans que generan la vista deben ubicarse el en archivo /WEB-INF/views.xml, el nombre lógico de la vista debe coincidir con el nombre del bean, veamos un ejemplo:

@Bean
public ViewResolver xmlViewResolver() {
    return new XmlViewResolver();
}

El archivo /WEB-INF/views.xml se define de la siguiente manera:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">

    <bean id="home" class="org.springframework.web.servlet.view.JstlView">
        <property name="url" value="/WEB-INF/views/index.jsp"/>
    </bean>
    
</beans>

En XML el nombre del bean lo asignamos con el atributo id="..." recordemos que este nombre debe coincidir con el nombre lógico devuelto por el controlador, también debemos establecer la propiedad url indicando el archivo JSP con que se debe generar la vista.

Si deseas conocer más detalladamente las configuración XML puedes ver los siguientes tutoriales:

ResourcBundleViewResolver

Funciona de manera similar al anterior, con la diferencia de que este utilizara el archivo .properties indicado para resolver las vistas, indicamos el nombre de dicho archivo usando el método setBasename("..."), debemos ubicar dicho archivo en la carpeta: src/main/resources.

@Bean
public ViewResolver rbViewResolver() {
    ResourceBundleViewResolver resolver = new ResourceBundleViewResolver();
    resolver.setBasename("myviews");
    return resolver;
}

El archivo src/main/resources/myviews.properties tiene el siguiente contenido:

home.(class)=org.springframework.web.servlet.view.JstlView
home.url=/WEB-INF/views/home.jsp

El nombre inicial home se refiere al nombre lógico que deseamos resolver, (class) define la clase usada para generar la vista, url indica el archivo JSP usado para generar dicha vista, colocamos en este archivo todas las vistas que deseemos resolver siguiente el formato.

ResourceBundleViewResolver

Nota: se recomienda almacenar los archivos usados para generar las vistas en la carpeta /WEB-INF/ ya que la misma no forma parte del del directorio publico de la aplicación, por lo que un usuario no podrá acceder directamente a las mismas.

InternalResourceViewResolver

Este es el ViewResolver que hemos utilizado en la mayoría de nuestros cursos, usando los métodos setPrefix("...") indicamos la carpeta donde se almacenan los archivos JSP en nuestro caso y con setSuffix("...") indicamos la extensión de los archivos.

@Bean
public ViewResolver viewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    return resolver;
}

El método setViewClass(...) permite establecer la clase que se utilizara para generar la vista, por defecto utiliza la clase JstlView que hemos venido usando desde el principio del tutorial.

Usando el nombre lógico que devuelve el controlador mas el prefijo y el sufijo, el archivo físico se resuelve de la siguiente manera:

image

Si extendemos la clase base WebMvcConfigurerAdapter podemos rápidamente utilizar este ViewResolver, solo debemos sobre-escribir el método configureViewResolver(...) de la siguiente manera:

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"carmelo.spring.controller"})
public class WebAppConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }
}

La clase WebMvcConfigurerAdapter implementa la interface WebMvcConfigurer utilizada para configurar los componentes Spring MVC, usando esta clase solo debemos sobre-escribir los métodos que nos interesan.

Usar varios ViewResolver

Podemos usar uno o mas ViewResolver en la misma aplicación web, solo debemos tener presente que para establecer la prioridad con que se utilizan los mismos debemos usar el método setOrder(0) en donde usaremos un número para indicar la prioridad de cada uno de ellos, el que tenga el valor más bajo se utilizará primero, si no puede resolver la vistas se utilizará el siguiente en el orden.

@Bean
public ViewResolver viewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    resolver.setOrder(2);
    return resolver;
}

@Bean
public ViewResolver xmlViewResolver() {
    XmlViewResolver resolver = new XmlViewResolver();
    resolver.setOrder(1);
    return resolver;
}

En este ejemplo para resolver las vistas se utilizará primero el XmlViewResolver y como segunda opción el InternalResourceViewResolver.

Existen muchas otras implementaciones del ViewResolver preparadas para trabajar con todo tipo de tecnologías, por ejemplo: JasperReportsViewResolver para generar reportes JasperReports, para utilizar plantillas Thymeleaf tenemos ThymeleafViewResolver, y muchas más que veremos a medida que avancemos con nuestra serie de tutoriales.

Comentarios

Temas relacionados

Entradas populares de este blog

tkinter Grid

Conectar SQL Server con Java

Controles y Contenedores JavaFX 8 - I

Histogramas OpenCV Python