目录
什么是模板引擎?
模板引擎就是为了解决HTML代码和Java代码混合在一起这个问题的,我们可以把HTML内容提取出来单独的放在一个文件中,称为模板,对于一些动态的内容,可以将这些内容在模板中使用占位符占位,当服务器把这些动态的内容计算好了之后,就可以把模板中占位符替换成动态计算的结果,然后把组装好的HTML格式的字符串在返回给浏览器
模板引擎的作用
模板引擎的使用原理
在Maven中央仓库搜索Thymeleaf
选择一个合适的版本,这里选择的是3.0.12
- <dependency>
- <groupId>org.thymeleafgroupId>
- <artifactId>thymeleafartifactId>
- <version>3.0.12.RELEASEversion>
- dependency>
我们创建一个hello.html放到webapp/WEB-INF/templates目录中
注意:web.xml和templates是同级目录,都在WEB-INF目录下,hello.html在templates目录下
- <body>
- <h3>模板技术学习h3>
- <p th:text="${message}">p>
- body>
说明:th:text是Thymeleaf的语法,后边介绍更多的Thymeleaf语法
创建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);
1. 点击启动tomcat
2. 输入路径hello
3. 观察结果
在上述代码中,有这三个关键类:
| 命令 | 功能 |
|---|---|
| th:text | 设置标签文本 |
| th:[HTML标签属性] | 设置标签属性 |
| th:if | 当表达式的结果为真时则显示内容,否则不显示 |
| th:each | 循环访问元素 |
Thymeleaf语法很多,此处只介绍最常用的几个
th:text功能就是设置标签文本
<p th:text="${message}">p>
常需要设置的属性: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");
运行程序,访问页面,点击就会跳转到对应的页面
th:if功能就是根据条件决定该标签是否显示
- <P th:if="${isLogin}">已经登陆P>
- <p th:if="${noLogin}">没有登陆p>
- wc.setVariable("isLogin",true);
- wc.setVariable("noLogin",false);
结果:只显示已经登陆
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方法
结果:

上述初始化引擎及解析器的代码,每个需要渲染页面的Servlet类都需要写一次,其实没有必要,一个完整的项目中,TemplateEngine和ServletContextTemplateResolver只需要创建一次并且初始化一次,为了完成这个目的,就需要使用Servlet中的ServletContext和ServletContextListener监听器
ServletContext是一个Servlet程序中全局储存信息的空间,服务器启动就创建,服务器关闭就销毁
理解Context:上下文/环境,常用于设置一些信息到上下文环境中,上下文环境中的对象就可以相互引用对方的数据

多个Servlet之间无法传递数据,但可以通过共享的上下文环境来设置或使用一些数据(数据传递)
ServletContext对象的重要方法
| 方法 | 说明 |
|---|---|
| void setAttribute(String name,Object obj) | 设置属性(键值对) |
| Object getAttribute(String name) | 根据name获取对应的值,如果name为不存在,返回null |
| void removeAttribute(String name) | 删除对应的属性 |
ServletContext类似Map结构,存放键值对数据
监听器属于一种设计模式,在Servlet运行过程中,会有一些特殊的“时机”供我们执行一些我们自己定义的逻辑,“监听器”就是可以让程序员在这些特殊的时机插入代码
此处学习的ServletContextListener,也是类似一种监听器的设计,在事件发生的时候不用我们自己写代码做事情,而是先注册一个方法到监听器,在某个事件发生后就会自动执行
此处我们需要使用监听器监听ServletContext的创建即可
结合ServletContext和Listener,我们就可以对之前的Thymeleaf引擎初始化代码做出调整
创建监听器
- @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,观察结果