Servlet + Spring 搭建Thymeleaf模板引擎小案例

Servlet + Spring 搭建Thymeleaf模板引擎小案例

前言

  Thymeleaf模板引擎比較傾向於前端,瞭解過一點前端的人都會很快上手的。之所以不用JSP模板,是因爲他還是原生的Java代碼。換句話來說,就是Thymeleaf可以直接查看效果無需啓動服務器,反之JSP就不行,必須依賴於服務器。這兩種模板屬於同一個方向,技術應用是要結合應用場景的。如果單純從學習角度來看,學習哪個技術都沒有錯。但如果是要做產品,做項目,那技術選型就非常關鍵了。

正文

  • 項目目錄:
    項目目錄
  • 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>vip.wulang</groupId>
  <artifactId>thymeleaf</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <properties>
    <mysql.version>5.1.34</mysql.version>
    <spring.version>4.3.0.RELEASE</spring.version>
    <hibernate.version>5.1.0.Final</hibernate.version>
    <druid.version>1.1.10</druid.version>
    <jpa.version>1.10.4.RELEASE</jpa.version>
    <test.version>4.12</test.version>
    <common.version>3.3.2</common.version>
    <servlet.version>3.1.0</servlet.version>
    <fastjson.version>1.2.47</fastjson.version>
    <slf4j.version>1.7.25</slf4j.version>
    <aspectj.version>1.8.10</aspectj.version>
    <validation.version>6.0.13.Final</validation.version>
    <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
  </properties>

  <dependencies>
    <!-- Spring Framework start -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!-- Spring Framework end -->

    <!-- Druid start -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>${druid.version}</version>
    </dependency>
    <!-- Druid end -->

    <!-- JPA start -->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>${jpa.version}</version>
      <exclusions>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-orm</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <!-- JPA end -->

    <!-- Hibernate start -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>${hibernate.version}</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>${hibernate.version}</version>
    </dependency>
    <!-- Hibernate end -->

    <!-- Mysql start -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>
    <!-- Mysql end -->

    <!-- Test start -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${test.version}</version>
      <scope>test</scope>
    </dependency>
    <!-- Test end -->

    <!-- Common start -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>${common.version}</version>
    </dependency>
    <!-- Common end -->

    <!-- Servlet start -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>
    <!-- Servlet end -->

    <!-- FastJson start -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>${fastjson.version}</version>
    </dependency>
    <!-- FastJson end -->

    <!-- Slf4j start -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <!-- Slf4j end -->

    <!-- Aspectj start -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>${aspectj.version}</version>
    </dependency>
    <!-- Aspectj end -->

    <!-- Validation start -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>${validation.version}</version>
    </dependency>
    <!-- Validation end -->

    <!-- Thymeleaf start -->
    <dependency>
      <groupId>org.thymeleaf</groupId>
      <artifactId>thymeleaf-spring4</artifactId>
      <version>${thymeleaf.version}</version>
    </dependency>
    <dependency>
      <groupId>org.thymeleaf</groupId>
      <artifactId>thymeleaf</artifactId>
      <version>${thymeleaf.version}</version>
    </dependency>
    <!-- Thymeleaf end -->

  </dependencies>

</project>

  • web.xml文件,我是基於Java配置文件的方式,你們也可以使用其他方式,個人喜好
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  
  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
  </context-param>

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>vip.wulang.config.MyApplicationContext</param-value>
  </context-param>
  
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <servlet>
    <servlet-name>IGTVGController</servlet-name>
    <servlet-class>vip.wulang.servlet.IGTVGController</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>IGTVGController</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  
</web-app>

  • MyApplicationContext.java,Spring容器
package vip.wulang.config;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.context.ServletContextAware;
import org.thymeleaf.ITemplateEngine;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.messageresolver.IMessageResolver;
import org.thymeleaf.messageresolver.StandardMessageResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletContext;
import java.io.IOException;
import java.util.Properties;

/**
 * @author CoolerWu on 2018/11/20.
 * @version 1.0
 */
@Configuration
@ComponentScan("vip.wulang")
public class MyApplicationContext implements ApplicationContextAware, ServletContextAware {

    private static ApplicationContext applicationContext;
    private static ServletContext servletContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MyApplicationContext.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        MyApplicationContext.servletContext = servletContext;
    }

    public static ServletContext getServletContext() {
        return servletContext;
    }

    @Bean
    public ITemplateResolver templateResolver() {
        ServletContextTemplateResolver servletContextTemplateResolver
                = new ServletContextTemplateResolver(servletContext);

        servletContextTemplateResolver.setTemplateMode(TemplateMode.HTML);
        servletContextTemplateResolver.setPrefix("/WEB-INF/templates/");
        servletContextTemplateResolver.setSuffix(".html");
        servletContextTemplateResolver.setCacheTTLMs(3600000L);
        servletContextTemplateResolver.setCacheable(true);

        return servletContextTemplateResolver;
    }

    @Bean
    public IMessageResolver messageResolver() throws IOException {
        ClassPathResource classPathResource = new ClassPathResource("./home.properties");
        Properties properties = new Properties();

        properties.load(classPathResource.getInputStream());

        StandardMessageResolver standardMessageResolver = new StandardMessageResolver();

        standardMessageResolver.setDefaultMessages(properties);

        return standardMessageResolver;
    }

    @Bean
    public ITemplateEngine templateEngine(ITemplateResolver templateResolver, IMessageResolver messageResolver) {
        TemplateEngine templateEngine = new TemplateEngine();

        templateEngine.setTemplateResolver(templateResolver);
        templateEngine.setMessageResolver(messageResolver);

        return templateEngine;
    }

}

  首先,筆者實現了兩個接口 ApplicationContextAware、ServletContextAware,Spring啓動時會自動注入 ApplicationContext、ServletContext。其次從官方文檔來看,我們先要配置 ITemplateResolver Bean,其實就是模板解析器,ServletContextTemplateResolver 是該接口的實現類,並在其中設置前綴、後綴、模板類型、是否緩存、緩存多久等信息。再配置 IMessageResolver Bean,就是消息解析器,這個也可以不用配置。默認/WEB-INF/templates/home.html在同一文件夾中找到屬性文件中的消息,並使用與模板相同的名稱,例如:

  1. /WEB-INF/templates/home_en.properties 用於英文文本。
  2. /WEB-INF/templates/home_es.properties 西班牙語文本。
  3. /WEB-INF/templates/home_pt_BR.properties 用於葡萄牙語(巴西)語言文本。
  4. /WEB-INF/templates/home.properties 對於默認文本(如果區域設置不匹配)。

而筆者則是設置的是在根目錄中,"./home.properties"。然後就到了最重要的一個環節了,ITemplateEngine 這個接口,就是模板引擎,裏面包含了之前了模板解析器、消息解析器等。至少需要配置模板解析器。以後要進行頁面跳轉也是通過模板引擎,我們可以當成模板引擎就是操作按鈕,其他的解析器都是已經在模板引擎裝配好了。

  • IGTVGController.java 配置,繼承了 GenericServlet
package vip.wulang.servlet;

import org.thymeleaf.ITemplateEngine;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import vip.wulang.config.MyApplicationContext;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author CoolerWu on 2018/11/20.
 * @version 1.0
 */
public class IGTVGController extends GenericServlet {

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        TemplateEngine templateEngine =
                ((TemplateEngine) MyApplicationContext.getApplicationContext().getBean(ITemplateEngine.class));

        WebContext webContext =
                new WebContext(request, response, MyApplicationContext.getServletContext(), request.getLocale());

        templateEngine.process("home", webContext, response.getWriter());
    }
}

  官方文檔介紹,Thymeleaf有一個上下文,這個上下文就是接口 IContext,而 IWebContext 擴展了該基礎接口,WebContext 就是實現類。

WebContext ctx = new WebContext(request, response, servletContext, request.getLocale());

這四個構造函數參數中只有三個是必需的,因爲如果沒有指定系統,將使用系統的默認語言環境(儘管在實際應用程序中不應該發生這種情況)。準備好上下文對象後,現在我們可以告訴模板引擎使用上下文處理模板(通過其名稱),並將響應編寫器傳遞給它,以便可以將響應寫入它:

templateEngine.process("home", webContext, response.getWriter());
  • home.properties
home.welcome=Bienvenido a nuestra tienda de comestibles!!!!
  • home.html
<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<head>
    <title>Good Thymes Virtual Grocery</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" media="all"
          href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
</head>

<body>

    <p th:text="#{home.welcome}">Welcome to our grocery store!</p>

</body>

</html>

  已經搭建完成了,不過需要注意的是:

<html xmlns:th="http://www.thymeleaf.org">

就是增加一個約束空間。只適用於html模板,也可以不可以不寫約束語句,即:

<!DOCTYPE html>

<html>

<head>
    <title>Good Thymes Virtual Grocery</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" media="all"
          href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" />
</head>

<body>

    <p data-th-text="#{home.welcome}">Welcome to our grocery store!</p>

</body>

</html>

這種語句通用於 Thymeleaf 的所有模板。看個人喜好。不啓動服務器打開:
不啓動服務器
啓動服務器打開:
啓動服務器

結束語

  更多詳情,瞭解官方文檔:https://www.thymeleaf.org/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章