JavaWeb进阶指南:Servlet与Thymeleaf整合全流程详解

大家好,我是袁庭新。今天介绍Servlet和Thymeleaf的整合过程。接下来,让我们一同深入探究其详细步骤与操作要点。

1.下载Thymeleaf依赖

想要使用Thymeleaf进行JavaWeb应用的开发,第一步就是要下载Thymeleaf的依赖包,具体步骤如下。

1.1 手动下载Thymeleaf依赖

1.使用浏览器访问Thymeleaf官网(www.thymeleaf.org),选择上方的【Download】按钮,如下图。

从上图可知,Thymeleaf当前最新版本为Thymeleaf 3.1.2.RELEASE,该版本要求Java SE的版本为8或更新的版本,这里我们使用的Java SE版本为11。

2.Thymeleaf官网为我们提供了多种引入Thymeleaf依赖的方式,例如Maven、Gradle以及直接下载Thymeleaf分发包和源码等。我们可以根据需要选择合适自己的方式来下载Thymleaf的依赖,如下图。

3.点击【Distribution packages】下方的【GitHub's releases distribution】链接,如下图所示。

4.跳转到GitHub页面,在Thymeleaf 3.1.2.RELEASE下的【Assets】中,点击"thymeleaf-3.1.1.RELEASE-dist.zip"下载发行包,如下图。

5.下载完成后,解压thymeleaf-3.1.2.RELEASE-dist.zip压缩包,可得到以下目录结构。

1.2 坐标下载Thymeleaf依赖

采用上述手动方式下载Thymeleaf依赖过于麻烦,如果我们的项目是Maven类型,将Thymeleaf添加到项目中最简单的方式是,并利用中央存储库中的Thymeleaf,你只需将所需的Thymeleaf依赖项添加到你的项目的pom.xml中即可。例如:

xml 复制代码
<dependency>
  <groupId>org.thymeleaf</groupId>
  <artifactId>thymeleaf</artifactId>
  <version>3.1.2.RELEASE</version>
</dependency>

2.配置模板引擎

2.1 模板引擎介绍

Thymeleaf的核心依赖包(thymeleaf-3.1.2.RELEASE.jar)中提供了一个名为TemplateEngine(模板引擎)的类。TemplateEngine类是Thymeleaf中最核心、最重要的类之一,Thymeleaf就是通过它来解析模板文件(例如HTML文件、XML文件、CSS文件等),最终渲染成动态网页进行展示的。

TemplateEngine类中包含了许多实用方法,其中最常用的就是下表中列出的这两个方法。

java 复制代码
public void setTemplateResolver(final ITemplateResolver templateResolver)

在使用TemplateEngine对模板文件进行处理之前,通常都需要为它设置一个ITemplateResolver类型的对象作为其模板解析器。通过这个ITemplateResolver(模板解析器)对象,我们可以对以下内容进行设置:

  • 模板文件的路径,包括前缀(prefix)和后缀(suffix);
  • 模板模式(TemplateMode):包括HTML、XML、TEXT、JAVASCRIPT、CSS、RAM等6种模式;
  • 缓存是否可用;
  • 缓存时间等。
java 复制代码
public final void process(final String template, final IContext context, final Writer writer)

模板引擎通过该方法实现对模板文件的解析,并最终渲染成一个动态网页。

对于一个JavaWeb应用而言,它只需要配置一个Thymeleaf模板引擎即可,因此这里我们需要使用单例模式对TemplateEngine进行配置,具体实现方式如下。

2.2 模板引擎实现

1.创建一个类型为Java Enterprise名为servlet-thymeleaf-project的JavaWeb项目。项目的GAV坐标中GroupId的值设置为com.ytx,其他保持默认。

2.在servlet-thymeleaf-project项目的pom.xml文件中添加如下的依赖。

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.ytx</groupId>
  <artifactId>servlet-thymeleaf-project</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>servlet-thymeleaf-project</name>
  <packaging>war</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
    <junit.version>5.8.1</junit.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
    <!-- Servlet依赖 -->
    <dependency>
      <groupId>jakarta.servlet</groupId>
      <artifactId>jakarta.servlet-api</artifactId>
      <version>6.0.0</version>
    </dependency>
    <!-- Thymeleaf依赖 -->
    <dependency>
      <groupId>org.thymeleaf</groupId>
      <artifactId>thymeleaf</artifactId>
      <version>3.1.2.RELEASE</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.3.2</version>
      </plugin>
    </plugins>
  </build>
</project>

3.这里我们引入的Servlet依赖版本是6.0.0,此版本的Servlet需要运行在Apache Tomcat 10.1.x版本上。因此,需要确保你电脑上安装的Tomcat版本正确。Apache官方对各版本的解释:tomcat.apache.org/whichversio...。这里我们对Tomcat的安装不展开介绍。

4.在servlet-thymeleaf-project项目的src目录下,创建一个com.ytx.thymeleaf包,并在该包下创建一个名为CustomTemplateEngine的Java类,通过该类对Thymeleaf的模板引擎进行配置,代码如下。

java 复制代码
package com.ytx.thymeleaf;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
import org.thymeleaf.web.servlet.IServletWebExchange;
import org.thymeleaf.web.servlet.JakartaServletWebApplication;
import java.io.IOException;

/**
 * 对于一个JavaWeb应用而言,我们只需要配置一套模板引擎即可,所有的请求都通过该模板引擎来解析网页。
 * 单例模式。本类中还提供了一个对请求进行解析的方法,方便我们使用。
 */
public class CustomTemplateEngine {
    private static CustomTemplateEngine webApplication;
    private TemplateEngine templateEngine;
    private JakartaServletWebApplication application;

    /** 单例模式:构造方法私有化处理 */
    private CustomTemplateEngine(HttpServletRequest request) {
        System.out.println("设置Thymeleaf模板引擎");
        // 创建Thymeleaf的JakartaServletWebApplication对象
        application = JakartaServletWebApplication.buildApplication(request.getServletContext());
        // 创建模板解析器对象
        final WebApplicationTemplateResolver templateResolver = new WebApplicationTemplateResolver(application);
        // 设置Thymeleaf的模板模式为HTML,除此之外Thymeleaf还支持处理其他5种模板,它们分别是XML、TEXT、JAVASCRIPT、CSS、RAW
        templateResolver.setTemplateMode(TemplateMode.HTML);
        // 设置模板文件的前缀(即路径)
        templateResolver.setPrefix("/WEB-INF/templates/");
        // 设置模板文件的文件后缀
        templateResolver.setSuffix(".html");
        // 设置缓存时间
        templateResolver.setCacheTTLMs(Long.valueOf(3600000L));
        // 设置缓存是否可用,开发阶段我们需要将缓存关闭,即设置为false
        templateResolver.setCacheable(false);
        // 创建模板引擎对象
        templateEngine = new TemplateEngine();
        // 为模板引擎设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);
    }

    /**
     * 获取WebApplication对象
     * @param request 请求对象
     * @return 返回CustomTemplateEngine对象
     */
    public static CustomTemplateEngine getInstance(HttpServletRequest request) {
        if (webApplication == null) {
            webApplication = new CustomTemplateEngine(request);
        }
        return webApplication;
    }

    /**
     * 处理模板文件
     * @param templateName 模板文件的名称
     * @param request 请求对象
     * @param response 响应对象
     * @throws IOException IO异常
     */
    public void processTemplate(String templateName, HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 创建IServletWebExchange对象
        IServletWebExchange webExchange = application.buildExchange(request, response);
        // 创建WebContext对象
        WebContext context = new WebContext(webExchange, webExchange.getLocale());
        // 设置响应体内容类型和字符集
        response.setContentType("text/html;charset=UTF-8");
        // 处理模板数据
        templateEngine.process(templateName, context, response.getWriter());
    }
}

这里我们采用了单例模式,CustomTemplateEngine中包含了一个私有(private)的构造方法以及一个返回其自身实例的getInstance()方法。在这个私有的构造方法中,我们对模板引擎TemplateEngine对象进行了配置,并使用WebApplicationTemplateResolver对象作为其模板解析器,分别配置了模板模式、模板文件的前缀和后缀、缓存等内容。

此外,CustomTemplateEngine类中还包含了一个processTemplate()方法,该方法内部对TemplateEngine实例的process()方法进行了调用。Servlet在处理完请求后,直接调用这个方法便可以对指定的模板文件进行访问。

温馨提示:对CustomTemplateEngine这个类,我们只需要理解其基本思想和原理即可,不用刻意的去记住代码。后面我们使用SpringMVC、Spring Boot等JavaWeb框架对Thymeleaf进行整合时仍然会涉及到这些配置,那时我们都是通过配置文件实现的,使用起来也更加方便。

3.在Servlet中使用Thymeleaf

在项目的src/main/java目录下新建一个com.ytx.servlet包,并在该包下创建一个名为IndexServlet的Servlet类,代码如下。

java 复制代码
package com.ytx.servlet;
import com.ytx.thymeleaf.CustomTemplateEngine;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet()方法执行...");
        // 获取CustomTemplateEngine实例,对TemplateEngine对象进行配置
        CustomTemplateEngine customTemplateEngine = CustomTemplateEngine.getInstance(request);
        // 通过TemplateEngine访问页面
        customTemplateEngine.processTemplate("index", request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

在这个Servlet的doXxx()方法中,我们通过CustomTemplateEngine的getInstance()静态方法获取到了CustomTemplateEngine对象,然后又调用了processsTemplate()方法将响应信息发送到指定的模板文件中展示。

需要特别注意的是,由于我们已经在CustomTemplateEngine的构造方法中设置了模板文件的前缀(/WEB-INF/templates/) 和后缀为(.html),因此我们在调用processTemplate()方法时,第一个形参只需要传入模板文件的名称"index"即可(不要.html后缀),Thymeleaf会自动在"/WEB-INF/templates/"目录下寻找index.html进行解析。

4.编写模板文件

1.在servlet-thymeleaf-project项目的webapp/WEB-INF/templates/目录下,新建一个名为index.html的模板文件,代码如下。

html 复制代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="UTF-8">
      <title>Index主页</title>
  </head>
  <body>
    <div th:text="访问动态网页Thymeleaf">访问静态页面HTML</div>
  </body>
</html>

2.将项目部署到Tomcat服务器中,然后启动服务器。使用浏览器访问http://localhost:8080/servlet-thymeleaf-project/index,浏览器展示结果如下。

复制代码
访问动态网页Thymeleaf

3.如果在启动Tomcat服务器时,IDEA控制台输出如下的错误提示日志信息,是因为执行catalina.sh脚本权限被拒绝导致的。

arduino 复制代码
Error running 'Tomcat 10.1.19': Cannot run program "/Users/yuanxin/Documents/ProgramSoftware/apache-tomcat-10.1.19/bin/catalina.sh" (in directory "/Users/yuanxin/Documents/ProgramSoftware/apache-tomcat-10.1.19/bin"): error=13, Permission denied

4.解决"error=13, Permission denied"问题的方法是::进入到Tomcat的bin目录下,执行以下命令。如果Tomcat服务器在启动过程中没有此问题,则忽略[3、4]步骤。

bash 复制代码
chmod a+x catalina.sh

5.总结

本文主要介绍了 Servlet 和 Thymeleaf 的整合过程。首先需下载 Thymeleaf 依赖,可手动或通过坐标添加到项目中。接着配置模板引擎,创建项目并添加相关依赖,利用单例模式在 CustomTemplateEngine 类中设置模板模式、文件路径等信息。然后在 IndexServlet 类的 doGet 等方法中获取 CustomTemplateEngine 实例处理模板文件。最后编写 index.html 模板文件,部署到 Tomcat 服务器并访问。过程中需注意依赖版本匹配及文件权限等问题。

相关推荐
Asthenia041241 分钟前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端
bobz9651 小时前
ovs patch port 对比 veth pair
后端
Asthenia04121 小时前
Java受检异常与非受检异常分析
后端
uhakadotcom1 小时前
快速开始使用 n8n
后端·面试·github
JavaGuide1 小时前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz9652 小时前
qemu 网络使用基础
后端
Asthenia04122 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端
Asthenia04122 小时前
Spring 启动流程:比喻表达
后端
Asthenia04123 小时前
Spring 启动流程分析-含时序图
后端
ONE_Gua3 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫