动态网页的模板引擎


一、什么是模板引擎?

jdbc预编译的操作命令对象,类似模板引擎:

select * from emp where id=?

这里的?就是占位符
这整个就相当于模板

preparedStatement.setInt(1,123)

1表示第几个占位符
123表示替换的值
模板和替换的值一起就组织为一个拼接的数据库可以执行的sql
select * from emp where id=123

作用:

  • 通过组织网页模板和数据,就可以返回一个动态的网页
  • 可以分离Servlet Java代码和HTML网页代码(相对于Servlet直接返回动态网页来说,模板引擎的优点)

网页模板引擎产品有很多:freemarker、velocity、thymeleaf(springboot官方默认的模板技术)

二、流程

在这里插入图片描述

三、Thymeleaf使用流程

1.通过maven引入依赖

在maven中央仓库搜索Thymeleaf
在这里插入图片描述
选择一个合适的版本,例如3.0.12:

扫描二维码关注公众号,回复: 13716157 查看本文章
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.12.RELEASE</version>
</dependency>

2.创建html版本文件

创建hello.html, 放到 webapps/WEB-INF/templates 目录中

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

th:text 是 Thymeleaf 的语法. 浏览器不能直接识别 th:text 属性.

3.编写Servlet代码

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

//使用thymeleaf模板技术
//创建一个模板引擎
TemplateEngine engine = new TemplateEngine();
//创建一个渲染网页模板的解析器:getServletContext是HttpServlet中的方法,返回Servlet上下文对象
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(getServletContext());
resolver.setCharacterEncoding("utf-8");//设置渲染时编码
//设置网页模板文件,路径的前缀和后缀
resolver.setPrefix("/WEB-INF/templates/");//前缀
resolver.setSuffix(".html");//后缀
//将模板解析器绑定到模板引擎中
engine.setTemplateResolver(resolver);

再设置数据和模板名称

//创建一个web上下文(环境的语义,里边有一个map结构,可以存放键值对的数据)
WebContext webContext = new WebContext(req,resp,getServletContext());
//设置了一个键值对的数据,可以理解为:为网页模板定义了一个变量(变量名为message,值为hello...)
//queryString传入msg=xxx
webContext.setVariable("message",req.getParameter("msg"));

//模板引擎渲染网页模板:第一个参数为模板名称,第二个参数为web上下文(里边保存了数据)
//会根据模板解析器设置的前缀+模板名称+后缀,为模板路径查找到模板,再组织模板内容+数据
//返回值就是渲染后的网页字符串
String html = engine.process("hello",webContext);

最后把渲染的html设置到响应正文

resp.getWriter().write(html);

四、Thymeleaf模板语法

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

$ {变量名}来引用Java代码中,设置的键值对数据(${键}就是值)

在这里插入图片描述
最终是把webContext设置的键值对数据中,键为message的值,设置到标签内容中

1.设置标签属性

一些常用的需要设置的属性

  • href
  • src
  • class
  • style

1.设置a标签的href属性:

前端代码:

<a th:href="${a1}">搜狗</a> <!-- 渲染为<a href="键为a1的值" -->
<a th:href="${a2}">百度</a>

后端代码:

//写网站的绝对路径还是要加http://写全
webContext.setVariable("a1","http://www.sogou.com");
webContext.setVariable("a2","http://www.baidu.com");

2.条件判断:

前端代码:

<p th:if="${isLogin}">已经登录了</p>

后端代码:

webContext.setVariable("isLogin",true);

true时,html中会包含< p >
false时,html中不包含< p >

3.循环:

th:each的功能就是可以循环的构造出多个元素
语法格式为:

th:each=“自定义的元素变量名称:${集合变量名称}”

简单直接遍历
前端代码:
在这里插入图片描述
后端代码:

//Arrays.asList中的参数为可变参数,是将可变参数数组转变为List
webContext.setVariable("names", Arrays.asList("张三","李四","王五"));

对User类进行访问:
在这里插入图片描述

五、只创建一个引擎实例

关于创建模板引擎和模板解析器
整个web应用,只需要初始化一次(代码中的对象engine、resolver,只需要创建一次)

原因:对象及属性不会改变
改造:放在Servlet的init方法

Servlet有三个生命周期方法:

  • init:初始化方法,只执行一次。tomcat在某个时间会创建Servlet对象,然后调用init方法
  • service:请求路径如果匹配到某个Servlet,就调用一次该Servlet的service方法
  • destory:销毁方法,只执行一次

还存在问题:每个Servlet都需要在init方法中创建(一个webapp中,还是有多个engine,resolver对象)
解决这个问题:ServletContext、ServletContextListener

1.什么是ServletContext?

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

很多地方都有Context这样的概念,他是一个语义上的概念
多个servlet间,无法直接传递数据,但可以通过共享的一个上下文环境,来设置/使用一些数据(数据传递)

ServletContext对象的重要方法:

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

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

代码示例:多个Servlet共享数据

//写入Context
@WebServlet("/write")
public class ContextWriteServlet extends HttpServlet {
    
    

    //write?data=xxx
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        String data = req.getParameter("data");
        //把数据写入Servlet共享的上下文环境
        ServletContext sc = getServletContext();
        sc.setAttribute("d",data);

        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().write("写入Context成功");
    }
}

//读取Context
@WebServlet("/read")
public class ContextReadServlet extends HttpServlet {
    
    

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        //把数据写入Servlet共享的上下文环境
        ServletContext sc = getServletContext();
        Object data = sc.getAttribute("d");

        resp.setContentType("text/html; charset=utf-8");
        resp.getWriter().write("读取Context:"+data);
    }
}

2.什么是监听器(Listener)

监听器,属于一种设计模式
如html中,标签中的事件——如< button onclick >
这个事件,其实就是监听器的设计模式

在html或js中,为一个dom元素,绑定一个事件(事件注册),不需要手动调用该事件的函数,而是在事件发生的时候,由浏览器来调用事件绑定的函数
这样事件发生需要执行的代码,和事件发生,两个就解耦

ServletContextListener,也是类似的一种监听器的设计。不要在事件发生的时候,自己写代码做事情,而是先注册一个函数/方法到监听器中,在某个事件发生后,就会自动执行

代码示例:监听ServletContext的创建

@WebListener
public class MyListener implements ServletContextListener {
    
    
    public void contextInitialized(ServletContextEvent sce) {
    
    
        // 这个会在 context 被创建的时候调用.
    	// 创建的时机在所有 Servlet 实例化之前.
    	System.out.println("ServletContext 创建");
    	// 通过 sce 的 getServletContext 方法获取到刚刚创建好的 ServletContext 对象
    	ServletContext context = sce.getServletContext();
    	context.setAttribute("message", "message 的初始值");
 }
    public void contextDestroyed(ServletContextEvent sce) {
    
    
        //这个会在 context 被销毁的时候调用. 此处我们不关注
    }
}

猜你喜欢

转载自blog.csdn.net/m0_51405559/article/details/123165235