【JavaWeb】模板引擎Thymeleaf

简介: 内容提取出来单独的放在一个文件中,称为模板,对于一些动态的内容,可以将这些内容在模板中使用占位符占位,当服务器把这些动态的内容计算好了之后,就可以把模板中占位符替换成动态计算的结果,然后把组装好的HTML格式的字符串在返回给浏览器

1. 初识模板引擎

什么是模板引擎?


模板引擎就是为了解决HTML代码和Java代码混合在一起这个问题的,我们可以把HTML内容提取出来单独的放在一个文件中,称为模板,对于一些动态的内容,可以将这些内容在模板中使用占位符占位,当服务器把这些动态的内容计算好了之后,就可以把模板中占位符替换成动态计算的结果,然后把组装好的HTML格式的字符串在返回给浏览器


模板引擎的作用


通过组织网页模板和数据,就可以返回一个动态的网页

可以分离Servlet Java代码和HTML网页代码(模板引擎的最大优点)

模板引擎的使用原理

image.png


2. Thymleaf的使用流程

2.1 通过Maven引入依赖

在Maven中央仓库搜索Thymeleaf

image.png


选择一个合适的版本,这里选择的是3.0.12

<dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>

   

2.2 创建HTML模板文件

我们创建一个hello.html放到webapp/WEB-INF/templates目录中

image.png

 

注意:web.xml和templates是同级目录,都在WEB-INF目录下,hello.html在templates目录下

<body>
    <h3>模板技术学习</h3>
    <p th:text="${message}"></p>
</body>


说明:th:text是Thymeleaf的语法,后边介绍更多的Thymeleaf语法


2.3 编写Servlet代码

创建HelloServlet类,注解为@WebServlet("/hello"),继承HttpServlet,重写doGet方法,在该类中先创建模板引擎和模板解析器,再设置数据和模板名称,最后再将渲染的html设置到响应正文


创建模板引擎和模板解析器

//创建模板引擎,用于最终完成最终页面渲染工作
        TemplateEngine engine = new TemplateEngine();
        //创建渲染网页模板的解析器
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(getServletContext());
        resolver.setCharacterEncoding("utf-8");//设置渲染时编码
        resolver.setPrefix("/WEB-INF/templates/");//前缀
        resolver.setSuffix(".html");//后缀
        //将解析器绑定到模板引擎中
        engine.setTemplateResolver(resolver);

   

设置数据和模板名称

//创建一个web上下文(里面有一个map结构,存放键值对)
        WebContext wc = new WebContext(req,resp,getServletContext());
        //设置一个键值对数据,键为message(模板中的变量),值为好好学习(要渲染的值),
        wc.setVariable("message","好好学习");
        //模板引擎渲染网页模板,第一个参数为模板名称,第二个参数为web上下文
        //根据模板解析器设置的前缀+模板名称+后缀为模板路径,查找到模板,再组织模板内容+数据
        //返回值就是渲染后的网页字符串
        String html = engine.process("hello",wc);
将渲染的html设置到响应正文 
        resp.setContentType("text/html; charset=utf-8");//设置响应编码
        resp.getWriter().write(html);

   

2.4 部署程序

1. 点击启动tomcat

image.png


2. 输入路径hello

image.png


3. 观察结果

image.png


2.5 小结

resovler的setPefix和setSuffix方法指定了从那个目录下筛选哪些文件

engine.process方法第一个参数指定了要加载哪个模板文件

webContext中指定了模板变量名和变量值的对应关系(类似哈希表结构),setVariable中的第一个参数要和模板文件中写的 ${message} 匹配

engine.process方法会把刚才的webContext里的值替换到模板中,并把最终结果写到resp对象中

在上述代码中,有这三个关键类:


TemplateEngine,核心功能是通过process()方法完成渲染工作

ServletContextTemplateResolver,核心功能是加载模板文件,为后边的渲染做准备

webContext,核心功能是组织模板变量要替换为什么值

3. Thymeleaf的常用语法

命令 功能
th:text 设置标签文本
th:[HTML标签属性] 设置标签属性
th:if 当表达式的结果为真时则显示内容,否则不显示
th:each 循环访问元素


Thymeleaf语法很多,此处只介绍最常用的几个


3.1 设置标签文本

th:text功能就是设置标签文本

<p th:text="${message}"></p>

 

3.2 设置标签属性

常需要设置的属性:href src class style...


示例:设置a标签的href属性

<a th:href="${url1}">百度</a>
    <a th:href="${url2}">搜狗</a>

 

对应后端代码:

wc.setVariable("url1","http://www.baidu.com");
        wc.setVariable("url2","http://www.sogou.com");

   

运行程序,访问页面,点击就会跳转到对应的页面

image.png


3.3 条件判断

th:if功能就是根据条件决定该标签是否显示

<P th:if="${isLogin}">已经登陆</P>
    <p th:if="${noLogin}">没有登陆</p>
        wc.setVariable("isLogin",true);
        wc.setVariable("noLogin",false);


结果:只显示已经登陆

image.png


3.4 循环

th:each的功能是可以循环的构造出多个元素


语法格式:th:each="自定义变量元素名称 : ${集合变量名称}"

<ul>
        <Li th:each="u : ${users}">
            姓名:<span th:text="${u.name}"></span>
            年龄:<span th:text="${u.age}"></span>
        </Li>
    </ul>
        wc.setVariable("users",Arrays.asList(
                new User("张三",21),
                new User("李四",23),
                new User("王五",28)
        ));
    private static class User{
        private String name;
        private int age;
        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public int getAge() {
            return age;
        }
    }

 

注意:创建的User类需要提供getter方法


结果:

image.png


4. 如何创建一个引擎实例?

image.png


上述初始化引擎及解析器的代码,每个需要渲染页面的Servlet类都需要写一次,其实没有必要,一个完整的项目中,TemplateEngine和ServletContextTemplateResolver只需要创建一次并且初始化一次,为了完成这个目的,就需要使用Servlet中的ServletContext和ServletContextListener监听器


4.1 什么是ServletContext

ServletContext是一个Servlet程序中全局储存信息的空间,服务器启动就创建,服务器关闭就销毁


Tomcat在启动时,它会为每个webapp都创建一个对应的ServletContext

一个Web应用的所有Servlet共享同一个ServletContext对象

可以通过HttpServlet.getServletContext()或HttpServletRequest.getServletContext()获取到当前webapp的ServletContext对象

理解Context:上下文/环境,常用于设置一些信息到上下文环境中,上下文环境中的对象就可以相互引用对方的数据

image.png

多个Servlet之间无法传递数据,但可以通过共享的上下文环境来设置或使用一些数据(数据传递)


ServletContext对象的重要方法

方法 说明
void setAttribute(String name,Object obj) 设置属性(键值对)
Object getAttribute(String name) 根据name获取对应的值,如果name为不存在,返回null
void removeAttribute(String name) 删除对应的属性


ServletContext类似Map结构,存放键值对数据


4.2 什么是监听器(Listener)

监听器属于一种设计模式,在Servlet运行过程中,会有一些特殊的“时机”供我们执行一些我们自己定义的逻辑,“监听器”就是可以让程序员在这些特殊的时机插入代码


此处学习的ServletContextListener,也是类似一种监听器的设计,在事件发生的时候不用我们自己写代码做事情,而是先注册一个方法到监听器,在某个事件发生后就会自动执行


此处我们需要使用监听器监听ServletContext的创建即可


4.3 修改Thymeleaf引擎初始化代码

结合ServletContext和Listener,我们就可以对之前的Thymeleaf引擎初始化代码做出调整


创建监听器,监听ServletContext的创建

当ServletContext创建完后,在contextInitialized方法中创建TemplateEngine实例和ServletContextTemplateResolver实例,并完成初始化

把创建出来的TemplateEngine实例放到ServletContext中

后续Servlet如果要使用TemplateEngine,那么直接从ServletContext获取之前创建好的实例

创建监听器

@WebListener
public class TemplateEngineListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        TemplateEngine engine = new TemplateEngine();
        ServletContext sc = sce.getServletContext();
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(sc);
        resolver.setCharacterEncoding("utf-8");
        resolver.setPrefix("/WEB-INF/templates/");
        resolver.setSuffix(".html");
        engine.setTemplateResolver(resolver);
        sc.setAttribute("engine",engine);
    }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    }
}


写前端test.html代码

<p th:text="${content}"></p>


写对应的后端代码

@WebServlet("/test")
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext sc = req.getServletContext();
        WebContext wc = new WebContext(req,resp,sc);
        wc.setVariable("content","写一篇博客");
        TemplateEngine engine = (TemplateEngine) sc.getAttribute("engine");
        String html = engine.process("test",wc);
        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().write(html);
    }
}


启动Tomcat,输入url,观察结果


 


相关文章
|
2月前
|
Web App开发 SQL Java
javaweb实现分页(二)
javaweb实现分页(二)
19 1
|
2月前
|
SQL 关系型数据库 MySQL
javaweb实现分页查询(一)
javaweb实现分页查询(一)
20 0
|
2月前
|
SQL 关系型数据库 MySQL
javaweb中实现分页,持续更新……
javaweb中实现分页,持续更新……
19 1
|
28天前
|
JSON Java 应用服务中间件
JavaWeb项目之乱码问题及如何解决
JavaWeb项目之乱码问题及如何解决
|
2月前
|
Java Spring 容器
[JavaWeb]——过滤器filter与拦截器Interceptor的使用、执行过程、区别
[JavaWeb]——过滤器filter与拦截器Interceptor的使用、执行过程、区别
|
2月前
JavaWeb 开发之 ServletContext 的和使用
JavaWeb 开发之 ServletContext 的和使用
23 1
|
23天前
|
JavaScript 前端开发
javaweb文件上传和下载
javaweb文件上传和下载
|
2月前
|
前端开发 NoSQL 应用服务中间件
javaweb单点登录的三种实现方式
javaweb单点登录的三种实现方式
35 0
|
2月前
|
SQL 前端开发 Java
Java后端进阶之路: JavaWeb(四)
Java后端进阶之路: JavaWeb
35 1
|
XML SQL Java
Java后端进阶之路: JavaWeb(三)
Java后端进阶之路: JavaWeb
34 1