Thymeleaf案例入门和基本语法讲解

一、Thymeleaf入门

1. Thymeleaf简介

1.1. 为什么需要Thymeleaf ?

在这里插入图片描述

当我们用servlet实现动态页面展示的时候,我们需要用writer.write()写出整个页面,以展示动态信息。但是代码实在是太冗长,根本无法维护,所以我们需要将视图展示抽取出来,单独作为一个View视图层。

但是我们如果只使用HTML作为视图的话,它是无法展示动态数据的,所以我们对HTML的新的期待:既能够正常显示页面,又能在页面中包含动态数据部分。而动态数据单靠HTML本身是无法做到的,所以此时我们需要引入服务器端动态视图模板技术

1.2. Thymeleaf的概念

Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎。类似JSP,Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。它的主要作用是在静态页面上渲染显示动态数据。

Thymeleaf的优势

  • SpringBoot官方推荐使用的视图模板技术,和SpringBoot完美整合。

  • 不经过服务器运算仍然可以直接查看原始值,对前端工程师更友好。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
	<!--
		th:text="${username}"表示在当前p标签的标签体里面显示服务器中的一个username的数据
	-->
    <p th:text="${username}">Original Value</p>
</body>
</html>

1.3. Thymeleaf的视图(物理视图和逻辑视图)

1.3.1. 物理视图

在这里插入图片描述

在Servlet中,将请求转发到一个HTML页面文件时,使用的完整的转发路径(绝对路径)就是物理视图。

/pages/user/login_success.html

如果我们把所有的HTML页面都放在某个统一的目录下,那么转发地址就会呈现出明显的规律:

/pages/user/login.html
/pages/user/login_success.html
/pages/user/regist.html
/pages/user/regist_success.html

……

路径的开头都是:/pages/user/

路径的结尾都是:.html

所以,路径开头的部分我们称之为视图前缀,路径结尾的部分我们称之为视图后缀。

1.3.2. 逻辑视图

物理视图=视图前缀+逻辑视图+视图后缀

上面的例子中:

视图前缀逻辑视图视图后缀物理视图
/pages/user/login.html/pages/user/login.html
/pages/user/login_success.html/pages/user/login_success.html

2. Thymeleaf的入门案例

第一步,加入jar包:(这些包需要放在src或者web-inf新建的lib目录下,然后右键选择Add as library,如果运行出错就在试试在idea项目中点击扳手🔧旁边的project structed最下面有一个problem,点击fix修复,此操作是将包导入部署目录中去。)
在这里插入图片描述

第二步,配置上下文参数:
在web-inf目录下的配置文件web.xml进行上下文配置:
在这里插入图片描述

物理视图=视图前缀+逻辑视图+视图后缀

<!-- 在上下文参数中配置视图前缀和视图后缀 -->
<context-param>
    <param-name>view-prefix</param-name>
    <param-value>/WEB-INF/view/</param-value>
</context-param>
<context-param>
    <param-name>view-suffix</param-name>
    <param-value>.html</param-value>
</context-param>

view-prefix表示视图前缀的配置,我们的前端视图页面保存到/WEB-INF/view/目录下,所以配置映射的就是这个路径。
在这里插入图片描述

说明:param-value中设置的前缀、后缀的值不是必须叫这个名字,可以根据实际情况和需求进行修改。

为什么要放在WEB-INF目录下?

原因:WEB-INF目录不允许浏览器直接访问,所以我们的视图模板文件放在这个目录下,是一种保护。以免外界可以随意访问视图模板文件。

访问WEB-INF目录下的页面,都必须通过Servlet转发过来,简单说就是:不经过Servlet访问不了。

这样就方便我们在Servlet中检查当前用户是否有权限访问。

那放在WEB-INF目录下之后,重定向进不去怎么办?

重定向到Servlet,再通过Servlet转发到WEB-INF下。(理解:应该为请求转发,servlet便能携带数据到WEB-INF)

第三步,创建Servlet基类:

这个类大家直接复制粘贴即可,将来使用框架(SpringMVC框架等)后,这些代码都将被取代。

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ViewBaseServlet extends HttpServlet {

    private TemplateEngine templateEngine;

    @Override
    public void init() throws ServletException {

        // 1.获取ServletContext对象
        ServletContext servletContext = this.getServletContext();

        // 2.创建Thymeleaf解析器对象
        ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);

        // 3.给解析器对象设置参数
        // ①HTML是默认模式,明确设置是为了代码更容易理解
        templateResolver.setTemplateMode(TemplateMode.HTML);

        // ②设置前缀
        String viewPrefix = servletContext.getInitParameter("view-prefix");

        templateResolver.setPrefix(viewPrefix);

        // ③设置后缀
        String viewSuffix = servletContext.getInitParameter("view-suffix");

        templateResolver.setSuffix(viewSuffix);

        // ④设置缓存过期时间(毫秒)
        templateResolver.setCacheTTLMs(60000L);

        // ⑤设置是否缓存
        templateResolver.setCacheable(true);

        // ⑥设置服务器端编码方式
        templateResolver.setCharacterEncoding("utf-8");

        // 4.创建模板引擎对象
        templateEngine = new TemplateEngine();

        // 5.给模板引擎对象设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);

    }

    protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 1.设置响应体内容类型和字符集
        resp.setContentType("text/html;charset=UTF-8");

        // 2.创建WebContext对象
        WebContext webContext = new WebContext(req, resp, getServletContext());

        // 3.处理模板数据
        templateEngine.process(templateName, webContext, resp.getWriter());
    }
}

第四步,创建index.html文件:
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试Thymeleaf</title>
</head>
<body>
<a href="/class13_thymeleaf/testThymeleaf">初步测试Thymeleaf</a>
</body>
</html>

第五步,创建Servlet:
在这里插入图片描述

在web.xml中进行如下的servlet路径映射,我这个项目名是class13_thymeleaf,当超链接访问的路径为/class13_thymeleaf/testThymeleaf便会由项目中web.xml配置servlet路径/testThymeleaf映射到对应的处理类中去,所以这同名的<servle-name>标签都要由一个访问路径和处理类对应,表示当访问到对应的路径时应该由哪个servlet类进行处理,web.xml文件可以有多个<servlet-mapping>标签中同名的<servlet-name>标签,但</servlet>标签下的<servlet-name>标签只能有一个同名,如果多个同名,映射路径都不知道匹配给哪个servlet类进行处理了。

<servlet>
  <servlet-name>TestThymeleafServlet</servlet-name>
  <servlet-class>com.drimwai.servlet.model.TestThymeleafServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>TestThymeleafServlet</servlet-name>
  <url-pattern>/testThymeleaf</url-pattern>
</servlet-mapping>

第六步,修改Servlet让其继承ViewBaseServlet:
继承了ViewBaseServlet后,使用了模板引擎的前端页面才能进行动态数据的渲染。
在这里插入图片描述

第七步,在doPost()方法中跳转到Thymeleaf页面:
这一步表示向哪个属性填充哪个值:request.setAttribute("username","奥巴马");而processTemplate(“target”,request,response)选择一个被填充对象,也就是target页面,之前已经定死了它的前缀(WEB-INF/view)和后缀(html);所以填充对象的位置确定即可

package com.drimwai.servlet;

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

public class TestThymeleafServlet extends ViewBaseServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("username","奥巴马");
        //请求转发跳转到/WEB-INF/view/target.html
        processTemplate("target",request,response);
    }
}

第八步,编写Thymeleaf页面代码:
第八步相当于创建一个你要用来渲染的模板,填充一些东西进去的,也可以看作实例化一个对象,里面有很多个属性,当第七步跳转到这个页面时,页面中的${username}属性就会被填充奥巴马字段)
在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>目标页面</title>
    </head>
    <body>
<!-- 
<p th:text="标签体新值">标签体原始值</p>
th:text作用:
- 不经过服务器解析,直接用浏览器打开HTML文件,看到的是『标签体原始值』
- 经过服务器解析,Thymeleaf引擎根据th:text属性指定的『标签体新值』去替换</span>『标签体原始值』
-->
        <!-- text是格式,这里新值填充h1标签这里,因为h1为文本类型,所以格式是text,根据填充位置的不同来确定到底要使用格式,例如可以文本框填充值类型应为value -->
        <h1 th:text="${username}">这里要显示一个动态的username</h1>
    </body>
</html>

由于target页面是存放到web-inf文件夹下,所以通过浏览器无法访问到target.html必须经过servlet请求转发才行,所以你在浏览器中地址栏中不会看到target.html出现

二、Thymeleaf基本语法

1. th名称空间

在这里插入图片描述

2. 表达式语法

2.1. 修改标签文本值

代码:

<p th:text="标签体新值">标签体原始值</p>

示例:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>目标页面</title>
</head>
<body>
<p th:text="${username}">username</p>
</body>
</html>

th:text作用:

  • 不经过服务器解析,直接用浏览器打开HTML文件,看到的是『标签体原始值』
  • 经过服务器解析,Thymeleaf引擎根据th:text属性指定的『标签体新值』去替换『标签体原始值』

2.2. 修改指定属性值

代码:

<input type="text" name="username" th:value="文本框新值" value="文本框旧值" />

示例:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>目标页面</title>
</head>
<body>
<input type="text" name="username" th:value="${username}" value="username" />
</body>
</html>

语法:任何HTML标签原有的属性,前面加上『th:』就都可以通过Thymeleaf来设定新值。

2.3. 解析URL地址

代码:

<!--
使用Thymeleaf解析url地址
-->
<!-- 当我们点击这个超链接时,会跳转到index页面处,这里不是填充到【访问index.html文本中】因为th:href,类型为href,所以是填充到a标签中的href中的-->
<a th:href="@{/index.html}">访问index.html</a>

示例:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>目标页面</title>
</head>
<body>
   <!-- 实际当我们点击这个超链接时,第一个href的值应该是旧值,第二个是填充值,填到旧值中去的-->
<a href="/class13_thymeleaf/index.html" th:href="@{/index.html}">访问index.html</a>
</body>
</html>

经过解析后得到:

/class13_thymeleaf/index.html

所以@{/}的作用是在字符串前附加『上下文路径』

这个语法的好处是:实际开发过程中,项目在不同环境部署时,Web应用的名字有可能发生变化。所以上下文路径不能写死。而通过@{/}动态获取上下文路径后,不管怎么变都不怕啦!

2.4. 解析携带参数的URL地址

代码:

<!--
使用Thymeleaf解析url地址
-->
<a th:href="@{/index.html(参数名=${动态数据},参数名='静态数据')}">访问index.html</a>

示例:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>目标页面</title>
</head>
<body>
<a th:href="@{/index.html(username=${username},password='123456')}">访问index.html</a>
</body>
</html>

2.5. 显示动态的首页

2.5.1. 首页地址使用URL地址解析

在这里插入图片描述

如果我们直接访问index.html本身,那么index.html是不需要通过Servlet,当然也不经过模板引擎,所以index.html上的Thymeleaf的任何表达式都不会被解析。

解决办法:通过Servlet访问index.html,这样就可以让模板引擎渲染页面了。

2.5.2. 使用Servlet+Thymeleaf动态解析首页地址

在这里插入图片描述

进一步的好处:

通过上面的例子我们看到,所有和业务功能相关的请求都能够确保它们通过Servlet来处理,这样就方便我们统一对这些请求进行特定规则的限定。

第一步,创建一个动态首页hello.html:
在这里插入图片描述

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>动态index页面</title>
</head>
<body>
<p th:text="${value}">value</p>
</body>
</html>

第二步,创建一个IndexServlet:

package com.drimwai.servlet;

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

public class IndexThymeleafServlet extends ViewBaseServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("value","这是一个动态的欢迎页面");
        //请求转发跳转到/WEB-INF/view/hello.html
        processTemplate("hello",request,response);
    }
}

第三步,修改web.xml把默认的首页指向servlet:

<!-- 指向首页的Servlet -->
<servlet>
  <servlet-name>indexThymeleafServlet</servlet-name>
  <servlet-class>com.drimwai.servlet.IndexThymeleafServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>indexThymeleafServlet</servlet-name>
  <url-pattern>/indexThymeleaf</url-pattern>
</servlet-mapping>

<!-- 把首页指向IndexServlet -->
<welcome-file-list>
  <welcome-file>indexThymeleaf</welcome-file>
</welcome-file-list>

2.6. 域对象在Thymeleaf中的使用

2.6.1. 域对象的回顾

域对象是在服务器中有一定作用域范围的对象,在这个范围内的所有动态资源都能够共享域对象中保存的数据。

2.6.1.1. 请求域

在请求转发的场景下,我们可以借助HttpServletRequest对象内部给我们提供的存储空间,帮助我们携带数据,把数据发送给转发的目标资源。

请求域:HttpServletRequest对象内部给我们提供的存储空间

2.6.1.2. 会话域

会话域的范围是一次会话,也就是一次请求有效

在这里插入图片描述

2.6.1.3. 应用域

应用域的范围是整个项目全局
在这里插入图片描述

2.6.2. 在Thymeleaf中操作域对象

我们通常的做法是,在Servlet中将数据存储到域对象中,而在使用了Thymeleaf的前端页面中取出域对象中的数据并展示

2.6.2.1. 操作请求域

Servlet中代码:

String requestAttrName = "helloRequestAttr";
String requestAttrValue = "helloRequestAttr-VALUE";

request.setAttribute(requestAttrName, requestAttrValue);

Thymeleaf表达式:

<p th:text="${helloRequestAttr}">request field value</p>

上面这样写等价于

<p th:text="${request.helloRequestAttr}">request field value</p>
2.6.2.2. 操作会话域

Servlet中代码:

// ①通过request对象获取session对象
HttpSession session = request.getSession();
// ②存入数据
session.setAttribute("helloSessionAttr", "helloSessionAttr-VALUE");

Thymeleaf表达式:拿name填value

<p th:text="${session.helloSessionAttr}">这里显示会话域数据</p>
2.6.2.3. 操作应用域

Servlet中代码:

// ①通过调用父类的方法获取ServletContext对象
ServletContext servletContext = getServletContext();
// ②存入数据
servletContext.setAttribute("helloAppAttr", "helloAppAttr-VALUE");

Thymeleaf表达式:

<p th:text="${application.helloAppAttr}">这里显示应用域数据</p>

2.7. 获取请求参数

当一个带参数的链接指向一个Servlet,那么该Servlet该如何获取参数,并显示到Thymeleaf的页面中呢?
这里的TestViewServlet跟上面的Servlet一样,可自行稍作改动即可。

2.7.1. 根据一个参数名获取一个参数值

代码:

<p th:text="${param.username}">这里替换为请求参数的值</p>

示例:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>目标页面</title>
</head>
<body>
<p th:text="${param.username}">这里替换为请求参数的值</p>
</body>
</html>

页面显示效果:
在这里插入图片描述

2.7.2. 根据一个参数名获取多个参数值

代码:

<p th:text="${param.team}">这里替换为请求参数的值</p>

页面显示效果:

在这里插入图片描述

如果想要精确获取某一个值,可以使用数组下标。页面代码:

<p th:text="${param.team[0]}">这里替换为请求参数的值</p>
<p th:text="${param.team[1]}">这里替换为请求参数的值</p>

页面显示效果:
在这里插入图片描述

2.7.3简化写法

当要根据一个参数名获取多个参数值时,例如获取到一个数组对象,其中每一个对象都有多个值。此时可以使用th:object="${所要获取的对象}"*

<table th:object="${person}">
    <tr th:text="*{name}"></tr> =>等价于<tr th:text="${person.name}"></tr>
</table>

2.8. 内置对象

所谓内置对象其实就是在Thymeleaf的表达式中可以直接使用的对象。

2.8.1. 基本内置对象

在这里插入图片描述

用法举例:

<h3>表达式的基本内置对象</h3>
<p th:text="${#request.getContextPath()}">调用#request对象的getContextPath()方法</p>
<p th:text="${#request.getAttribute('helloRequestAttr')}">调用#request对象的getAttribute()方法,读取属性域</p>

基本思路:

  • 如果不清楚这个对象有哪些方法可以使用,那么就通过getClass().getName()获取全类名,再回到Java环境查看这个对象有哪些方法
  • 内置对象的方法可以直接调用
  • 调用方法时需要传参的也可以直接传入参数
2.8.2. 公共内置对象

在这里插入图片描述

Servlet中将List集合数据存入请求域:

request.setAttribute("aNotEmptyList", Arrays.asList("aaa","bbb","ccc"));
request.setAttribute("anEmptyList", new ArrayList<>());

页面代码:

<p>#list对象isEmpty方法判断集合整体是否为空aNotEmptyList:<span th:text="${#lists.isEmpty(aNotEmptyList)}">测试#lists</span></p>
<p>#list对象isEmpty方法判断集合整体是否为空anEmptyList:<span th:text="${#lists.isEmpty(anEmptyList)}">测试#lists</span></p>

公共内置对象对应的源码位置:

在这里插入图片描述

2.9. 分支与迭代

2.9.1. if和unless分支

让标记了th:if、th:unless的标签根据条件决定是否显示。

示例的Servlet代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    //往request域对象中存储List集合
    request.setAttribute("aNotEmptyList", Arrays.asList("aaa","bbb","ccc"));
    request.setAttribute("anEmptyList", new ArrayList<>());

    //调用方法渲染视图
    processTemplate("list", request, response);
}

示例的HTML代码:

anNotEmptyList中有数据

anEmptyList中没有有数据

<!--
使用Thymeleaf的th:if和th:unless来控制标签的显示与否
-->
<p th:unless="${#lists.isEmpty(aNotEmptyList)}">anNotEmptyList中有数据</p> 显示
<p th:if="${#lists.isEmpty(aNotEmptyList)}">anNotEmptyList中没有有数据</p>

<p th:unless="${#lists.isEmpty(anEmptyList)}">anEmptyList中有数据</p>
<p th:if="${#lists.isEmpty(anEmptyList)}">anEmptyList中没有数据</p> 显示
2.9.2. switch分支
<h3>测试switch</h3>
<div th:switch="${level}">
    <p th:case="level1">银牌会员</p>
    <p th:case="level2">金牌会员</p>
    <p th:case="level3">白金会员</p>
    <p th:case="level4">钻石会员</p>
</div>
2.9.3. each循环

示例的Servlet代码:

List<String> userList = new ArrayList<>();
userList.add("张三");
userList.add("李四");
userList.add("王五");
userList.add("赵六");
userList.add("田七");

request.setAttribute("userList", userList);

示例的HTML代码:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户列表展示页面</title>
</head>
<body>
    <!--
        获取域对象中的集合,并且遍历展示
    -->
    <table border="1" cellspacing="0" width="400" align="center">
        <thead>
            <tr>
                <th>下标</th>
                <th>计数</th>
                <th>用户名</th>
            </tr>
        </thead>
        <tbody th:if="${#lists.isEmpty(userList)}">
            <tr>
                <td colspan="3">用户信息为空,没法遍历展示数据</td>
            </tr>
        </tbody>
        <tbody th:unless="${#lists.isEmpty(userList)}">
            <!--
            使用th:each进行遍历迭代
                1. th:each写在哪? 每遍历出一条数据就要添加一个什么标签就写在什么标签上
                2. th:each="遍历出来的数据 : 要遍历的数据"
                3. 我们怎么使用遍历出来的数据: ${遍历出来的数据}

            我们怎么获取遍历出来的每一个数据的状态:th:each="遍历出来的数据,遍历出来的数据的状态 : 要遍历的数据"
                遍历出来的数据的状态又包含:
                    index表示下标
                    count表示计数
                    even表示是否是奇数
                    odd表示是否是偶数
                    current表示遍历出来的当前元素
                    first表示第一个元素
                    last表示最后一个元素
                例如: 下标
            -->
            <tr th:each="user,status : ${userList}">
                <td th:text="${status.index}"></td>
                <td th:text="${status.even}"></td>
                <td th:text="${user}"></td>
            </tr>
        </tbody>
    </table>
</body>
</html>

2.10. Thymeleaf包含其他模板文件

2.10.1. 应用场景

抽取各个页面的公共部分:
在这里插入图片描述

2.10.2. 操作步骤

第一步,创建segment.html页面存放公共代码片段:

使用th:fragment来给这个片段命名:

<div id="inner" th:fragment="header">
    <p>被抽取出来的头部内容</p>
</div>

第二步,在需要的页面中进行包含:

语法效果特点
th:insert把目标的代码片段整个插入到当前标签内部它会保留页面自身的标签
th:replace用目标的代码替换当前标签它不会保留页面自身的标签
th:include把目标的代码片段去除最外层标签,然后再插入到当前标签内部它会去掉片段外层标记,同时保留页面自身标记

页面代码举例:

<!-- 代码片段所在页面的逻辑视图 :: 代码片段的名称 -->
<div id="outer" th:insert="segment :: header">
    div标签的原始内容
</div>

<div id="outer" th:replace="segment :: header">
    div标签的原始内容
</div>

<div id="outer" th:include="segment :: header">
    div标签的原始内容
</div>

2.11.Base标签

在这里插入图片描述

引入静态资源:

以相对路径导入样式文件时,需要使用../表示回退到当前目录的上一级目录,这样既不好看又繁琐。而当我们使用绝对路径引入时,可以看到前缀都一致,此处为http://localhost8080/pro10/,我们用一个常量存储然后要使用时就加上这个常量,这是我们就用到了base标签。

<base href="http://localhost8080/pro10/" />
<!--@表示base标签中的内容,所以此处等价于 http://localhost8080/pro10/css/xxx.css-->
<link th:href="@{/css/xxx.css}">  
访问路径

某个页面,如index.html在web文件夹下,那么该页面中的超链接<a href="/edit.html">点击</a>以相对路径写时,我们点击访问后的访问路径时基于index.html页面所在的位置,就是在web文件夹下的edit.html文件。使用绝对路径比较灵活,我们可以随意定位到某个文件夹下的资源。还是使用base标签。

<a th:href="@{/edit.html}">奏折详情</a>  //访问静态资源
<a th:href="@{/edit (key1=value1,key2=value2)}"></a> //访问某个servlet,此处应该是直接访问xml中配置为/edit的servlet

2.11.发送请求参数

超链接
  • 用一个{/所要访问的servlet(携带参数名1=参数值1,携带参数名2=参数值2)}
<a th:href="@{/work(method='showMemorialsDetail',memorialsId=${memorials.memorialsId})}">奏折详情</a>
form表单
<form th:action="@{/work}" method="post">

    <input type="hidden" name="method" value="feedBack" />
    <input type="hidden" name="memorialsId" th:value="${memorials.memorialsId}"/>
    <textarea name="feedbackContent"></textarea>
    <button type="submit">御批</button>

</form>
请求JS方法(含参数)
<td th:onclick="'deleteOne('+${person.name}+')'">删除</td>

上面这种使用字符串拼接的方式很麻烦,我们使用下面这一种:

<td th:onclick="|deleteOne(${person.name})|"></td>

补充一下JS:

function deleteOne(name){
    if(confirm('是否确认删除?')){  //点击确认if为true,指向if里面的内容
        window.location.href='Deleteservlet?personName='+name; //将当前地址栏修改为,即跳转
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值