👉引言💎
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。 热爱写作,愿意让自己成为更好的人............
铭记于心 | ||
🎉✨🎉我唯一知道的,便是我一无所知🎉✨🎉 |
Thmeleaf
MVC
为什么需要MVC
我们之前在书城项目第二阶段做登录的时候,曾经提出过优化登录失败后的处理
虽然说可以实现在登录失败之后跳转回到登录页面,并且展示失败信息,但是代码实在是太恶心了,根本没法维护,所以我们需要将视图展示抽取出来,单独作为一个View视图层
但是我们如果只使用HTML作为视图的话,它是无法展示动态数据的,所以我们对HTML的新的期待:既能够正常显示页面,又能在页面中包含动态数据部分。而动态数据单靠HTML本身是无法做到的,所以此时我们需要引入服务器端动态视图模板技术。
MVC概念
M:Model模型
V:View视图
C:Controller控制器
MVC是在表述层开发中运用的一种设计理念。主张把封装数据的『模型』、显示用户界面的『视图』、协调调度的控制器分开。
好处:
- 进一步实现各个组件之间的解耦
- 让各个组件可以单独维护
- 将视图分离出来以后,我们后端工程师和前端工程师的对接更方便
Thymeleaf的简介
1 Thymeleaf的概念
Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎。类似JSP,Velocity,FreeMaker等, 它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。它的主要作用是在静态页面上渲染显示动态数据
2 Thymeleaf的优势
- SpringBoot官方推荐使用的视图模板技术,和SpringBoot完美整合。
- 不经过服务器运算仍然可以直接查看原始值,对前端工程师更友好。
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p th:text="${username}">Original Value</p> </body> </html>
3 物理视图和逻辑视图
物理视图
在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
所以,路径开头的部分我们称之为视图前缀,路径结尾的部分我们称之为视图后缀。
逻辑视图
逻辑视图
物理视图=视图前缀+逻辑视图+视图后缀
上面的例子中:
视图前缀 | 逻辑视图 | 视图后缀 | 物理视图 |
/pages/user/ | login | .html | /pages/user/login.html |
/pages/user/ | login_success | .html | /pages/user/login_success.html |
Thymeleaf的入门案例
配置上下文参数
物理视图=视图前缀+逻辑视图+视图后缀
<!-- 在上下文参数中配置视图前缀和视图后缀 --> <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>
说明:param-value中设置的前缀、后缀的值不是必须叫这个名字,可以根据实际情况和需求进行修改。
为什么要放在WEB-INF目录下?
原因:WEB-INF目录不允许浏览器直接访问,所以我们的视图模板文件放在这个目录下,是一种保护。以免外界可以随意访问视图模板文件。
访问WEB-INF目录下的页面,都必须通过Servlet转发过来,简单说就是:不经过Servlet访问不了。
这样就方便我们在Servlet中检查当前用户是否有权限访问。
那放在WEB-INF目录下之后,重定向进不去怎么办?
重定向到Servlet,再通过Servlet转发到WEB-INF下。
创建Servlet基类
这个类大家直接复制粘贴即可,将来使用框架后,这些代码都将被取代。
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()); } }
入门案例代码
1 创建index.html文件
2 index.html编写超链接访问Servlet
<a href="/webday08/TestThymeleafServlet">初步测试Thymeleaf</a>
3 创建Servlet
<servlet> <servlet-name>testThymeleafServlet</servlet-name> <servlet-class>com.atguigu.servlet.TestThymeleafServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>testThymeleafServlet</servlet-name> <url-pattern>/testThymeleaf</url-pattern> </servlet-mapping
5 修改Servlet让其继承ViewBaseServlet
6 在doPost()方法中跳转到Thymeleaf页面
package com.atguigu.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author Leevi * 日期2021-05-13 09:15 */ 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); } }
7 Thymeleaf页面代码
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>目标页面</title> </head> <body> <h1 th:text="${username}">这里要显示一个动态的username</h1> </body> </html>
Thymeleaf的基本语法
1 th名称空间
xmlns:th="http://www.thymeleaf.org"
2 表达式语法
修改标签文本值
代码示例:
<p th:text="标签体新值">标签体原始值</p>
th:text作用
- 不经过服务器解析,直接用浏览器打开HTML文件,看到的是『标签体原始值』
- 经过服务器解析,Thymeleaf引擎根据th:text属性指定的『标签体新值』去替换『标签体原始值』
字面量和变量
『字面量』是一个经常会遇到的概念,我们可以对照『变量』来理解它的含义。
// a是变量,100是字面量 int a = 100; System.out.println("a = " + a);
- 变量:变量名字符串本身不是它的值,它指向的才是它的值
- 字面量:它就是字面上的含义,我们从『字面』上看到的直接就是它的值
现在我们在th:text属性中使用的就是『字面量』,它不指代任何其他值。
修改指定属性值
代码示例:
<input type="text" name="username" th:value="文本框新值" value="文本框旧值" />
语法:任何HTML标签原有的属性,前面加上『th:』就都可以通过Thymeleaf来设定新值。