devstory

Utiliser plusieurs ViewResolvers dans Spring Boot

  1. Objectif de la publication
  2. Créer un projet C Spring Boot
  3. Configurer le fichier pom.xml
  4. Configurer des ViewResolver
  5. Controller
  6. Views

1. Objectif de la publication

Normalement, dans une application Spring, vous devez utiliser uniquement une technology pour la couche View, soit Thymeleaf, JSP ou FreeMarker,... Cependant, vous pouvez utiliser plusieurs technologies pour la couche View. Dans cet article, je vous donnerai des instructions de la création une telle application.
OK, nous allons créer une application qui utilise toutes les trois technologies telles que Thymeleaf, JSP & FreeMarker pour la couche View.

2. Créer un projet C Spring Boot

3. Configurer le fichier pom.xml

Pour utiliser les technologies JSP, Thymeleaf, FreeMarker vous devez posséder des bibliothèques comme ci-dessous :
<!-- Thymeleaf -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- FreeMarker -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- Web -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JSP -->
<dependency>
   <groupId>org.apache.tomcat.embed</groupId>
   <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!-- JSTL -->
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
</dependency>
Le contenu complet du fichier pom.xml:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
      http://maven.apache.org/xsd/maven-4.0.0.xsd">
      
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.o7planning</groupId>
    <artifactId>SpringBootMultiViewResolver</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SpringBootMultiViewResolver</name>
    <description>Spring Boot + Multi ViewResolver</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        
        <!-- Thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        
        <!-- FreeMarker -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>        
        
        <!-- Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- JSP -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

        <!-- JSTL -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

4. Configurer des ViewResolver

Lorsque vous développez un projet Spring Boot, vous devez habituellement utiliser une technology pour la couche View (JSP, Thymeleaf, ..), Spring Boot va automatiquement configurer un ViewResolver avec lequel vous pouvez travailler. Dans le cas où vous utilisez plusieurs technologies pour la couche View, vous devez configurer tous les ViewResolver nécessaires.
Voici est une illustration du flux (Flow) d'une application Spring dans la cas où vous utilisez 1 ViewResolver.
Au cas où vous utilisez plusieurs technologies pour la couche View, plusieurs ViewResolver vont participer aux flux (flow) de l'application. Les ViewResolver sont arrangés par ordre de priorité (0, 1, 2, ..). Si ViewResolver (0) ne trouve pas "View Name" nécessaire, ViewResolver (1) sera utilisé, ...
Configurer Thymeleaf ViewResolver.
ThymeleafViewResolverConfig.java
package org.o7planning.sbmultiviewresolver.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;

@Configuration
public class ThymeleafViewResolverConfig {

    @Bean
    public ViewResolver thymeleafViewResolver() {

        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();

        viewResolver.setTemplateEngine(thymeleafTemplateEngine());
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setOrder(0);

        // Important!!
        // th_page1.html, th_page2.html, ...
        viewResolver.setViewNames(new String[] { "th_*" });

        return viewResolver;
    }

    // Thymeleaf template engine with Spring integration
    @Bean
    public SpringTemplateEngine thymeleafTemplateEngine() {

        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(thymeleafTemplateResolver());
        templateEngine.setEnableSpringELCompiler(true);

        return templateEngine;
    }

    @Bean
    public SpringResourceTemplateResolver springResourceTemplateResolver() {
        return new SpringResourceTemplateResolver();
    }

    // Thymeleaf template resolver serving HTML 5
    @Bean
    public ITemplateResolver thymeleafTemplateResolver() {

        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();

        templateResolver.setPrefix("templates/");
        templateResolver.setCacheable(false);
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCharacterEncoding("UTF-8");

        return templateResolver;
    }
 
}
Dans cette application, nous configurons Thymeleaf ViewResolver avec la plus haute priorité (order = 0).
Remarque : Deuxième priorité sera utilisée. Par conséquent, vous devez établir des ordres de "View Name" qui seront servis par Thymeleaf ViewResolver.
// Important!!
// th_page1.html, th_page2.html, ...
viewResolver.setViewNames(new String[] { "th_*" });
Configurer FreeMarker ViewResolver.
FreeMarkerViewResolverConfig.java
package org.o7planning.sbmultiviewresolver.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;

@Configuration
public class FreeMarkerViewResolverConfig {

    @Bean(name = "viewResolver")
    public ViewResolver getViewResolver() {
        FreeMarkerViewResolver viewResolver = new FreeMarkerViewResolver();

        viewResolver.setCache(true);
        viewResolver.setPrefix("/freemarker/");
        viewResolver.setSuffix(".ftl");
        viewResolver.setOrder(1);
        return viewResolver;
    }

    @Bean(name = "freemarkerConfig")
    public FreeMarkerConfigurer getFreemarkerConfig() {
        FreeMarkerConfigurer config = new FreeMarkerConfigurer();

        // Folder containing FreeMarker templates.
        // 1 - "/WEB-INF/views/"
        // 2 - "classpath:/templates"
        config.setTemplateLoaderPath("classpath:/templates");
        return config;
    }
    
}
La principe d'exploitation de FreeMarker ViewResolver:
Configurer JSP ViewResolver.
Remarque : JSP ViewResolver doit être établit de basse priorité. Ceci est commenté dans les documents de Spring.
JspViewResolverConfig.java
package org.o7planning.sbmultiviewresolver.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@Configuration
public class JspViewResolverConfig {

    @Bean
    public ViewResolver jspViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setContentType("text/html");
        
        // Make sure > Thymeleaf order & FreeMarker order.
        viewResolver.setOrder(1000);
        
        return viewResolver;
    }
    
}
Les principes d'exploitation de JSP ViewResolver:

5. Controller

MainController.java
package org.o7planning.sbmultiviewresolver.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MainController {

    @RequestMapping(value = { "/testJsp" }, method = RequestMethod.GET)
    public String testJspView() {

        return "testJsp";
    }

    @RequestMapping(value = { "/testThymeleaf" }, method = RequestMethod.GET)
    public String testThymeleafView() {

        return "th_page1";
    }
    
    @RequestMapping(value = { "/testFreeMarker" }, method = RequestMethod.GET)
    public String testFreeMarkerView() {

        return "testFreeMarker";
    }
    
}

6. Views

th_page1.html (Thymeleaf)
<!DOCTYPE html>

<html lang="en">
   <head>
       <title>Thymeleaf</title>
   </head>
   <body>
   
      <h2>Thymeleaf Page</h2>
      <p>templates/th_page1.html</p>
      
   </body>
</html>
freemaker/testFreeMarker.ftl (FreeMarker)
<!DOCTYPE html>

<html lang="en">
   <head>
       <title>FreeMarker</title>
   </head>
   <body>
   
      <h2>FreeMarker Page</h2>
      <p>templates/freemarker/testFreeMarker.ftl</p>
      
   </body>
</html>
testJsp.jsp
<!DOCTYPE html>

<html lang="en">
   <head>
       <title>JSP</title>
   </head>
   <body>
   
      <h2>JSP Page</h2>
      <p>WEB-INF/jsp/testJsp.jsp</p>
      
   </body>
</html>

Tutoriels Spring Boot

Show More