模板技术和监听器

使用模板技术

  • 自己动手的缺点(Object - > HTML格式):
    1. 代码繁琐
    2. 数据和逻辑耦合了
      数据: html结构
      逻辑:循环、字符串处理等
      (1)容易出错
      (2)一旦需要修改,很麻烦
  • 模板引擎就是为了解决上面遇到的, HTML 和 Java 混在一起的问题. 我们可以把 HTML 的内容提取出来, 放到单独的文件中,称为 模板.
    举例:
    js 中的模板字符串`hello ${user.username},Bye!’ => String
    String.format(“hello %s,Byte”, user.username) => String
  • web中要使用模板技术的时候,大多不是前后端分离的,而是后端直接产生html内容!
  • 模板文件只是 web应用生成资源的一个中间事务,不是真正的web资源

Web应用上的模板技术

JSP、Thymeleaf(SpringBoot建议使用Thymeleaf 作为默认模板)、FreeMarker …

  1. 添加依赖
    在这里插入图片描述
  2. 在普通类中使用
    (1)模板引擎(TemplateEngin)
    (2)模板解析器(TemplateResolver)
    (3)供模板渲染(render)的数据/上下文(Context)
    (4)模板文件=>路径的形式体现=>真实需要的其实是模板文件里的内容
    (5)模板处理之后的结果字符串
    在这里插入图片描述
    编译出的类的根路径

资源根路径下的所有文件,编译时在这里插入图片描述
会被复制到类的根路径下
在这里插入图片描述

public static void main(String[] args) throws UnsupportedEncodingException {
        //1.创建一个模板引擎对象
        TemplateEngine engine=new TemplateEngine();

        //2.创建一个解析器对象&&对解析器进行必要的配置
        ClassLoaderTemplateResolver resolver=new ClassLoaderTemplateResolver();
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCharacterEncoding("utf-8");//字符集
        resolver.setCacheable(false);//取消缓存
        resolver.setPrefix("templates/"); //类根路径下 /templates/
        resolver.setSuffix(".html");//后缀名

        //3.把解析器对象,关联到引擎对象中
        engine.setTemplateResolver(resolver);

        //4.准备Context对象&&为其添加需要渲染的数据
        User user=new User();
        user.uid=1998;
        user.username="张三";
        user.password="123456";
        List<Integer> list= Arrays.asList(1,2,3,4,5);
        Context context=new Context();
        context.setVariable("data",user);//把user对象以data置名进行渲染
        context.setVariable("someString","你好世界");//可以是字符串
        context.setVariable("number",list);//可以是数组

        //5.传入模板名称+context,进行模板渲染
        String result = engine.process("demo", context);

        //模板文件的路径到底在哪
        //由于我们这里是ClassLoaderTemplateResolver
        //cl就是加载ThymeleafDemo类时的类加载器对象
        ClassLoader cl = ThymeleafDemo.class.getClassLoader();
        //拼接 Prefix + template + Suffix => template/demo.html
        URL resource = cl.getResource("templates/demo.html");
        System.out.println(URLDecoder.decode(resource.toString(), "UTF-8"));

        //打印最终的字符串
        System.out.println(result);
    }
<!doctype html>
<html lang="zh-hans" xmlns:th="http://www.thymeleleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>模板技术演示</title>
</head>
<body>
  <h1 th:text="${data.username}">随便写什么</h1>
  <h2 th:text="${data.uid}">会被真实的uid替换</h2>
  <h2 th:text="${data.password}"></h2>
</body>
</html>

结果:
在这里插入图片描述
thymeleaf 中的模板语言简介

背景知识xmlns:th= “http://www.thymeleaf.org”,是XML标准指定命名空间(namespace ns)

th:xxxx xxxx标签是输入th 命名空间下的(xmlns:th不写,只是有警告提示,不影响使用)

thymeleaf提供的所有模板语言功能都是以th:开头的标签

  1. th:text=“表达式语言” : ${data.uid} => user对象中的uid 属性 或者 user对象的getUid()方法
    < h1>(替换掉这里的内容)< /h1>
    th:text ="“你好!’+ ${data.username}”
    在这里插入图片描述
  2. th:href = ""https://www.baidu.com/q?wd=’+ ${data.username}"替换标签中href属性
    (除了几个特殊的标签,其他的都是替换标签中默认的属性)
<a href="https://www.qq.com" th:href="'https://www.baidu.com/q?wd='+ ${data.username} ">访问百度</a>
<img src="/img/demo.jpg" th:src="'https://some.img.com/img?id=' + ${data.uid}">

在这里插入图片描述

  1. th:text = "每个元素的名称 : ${列表}"
<ol>
    <li th:each="s : ${number}">
        <p th:text="${s}"></p>
    </li>
</ol>

在这里插入图片描述

  1. th : if = " " :满足条件时
    th : unless = " " :不满足条件时
<p th:if="${someString}">有someString</p>
<p th:unless="${someString}">没有someString</p>

在这里插入图片描述

  1. 其他的基本视为直接替换标签的属性,类似 th:href、th:src、th:class、th:id

在web应用中把模板用起来

  1. 有个专门的解析器对象(ServletContextResolver)
  2. 有个专门的Context对象(WebContext)
    在这里插入图片描述
@WebServlet("/template-demo")
public class TemplateDemoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.创建一个模板引擎对象
        TemplateEngine engine=new TemplateEngine();

        //2.创建一个解析器对象
        ServletContext servletContext = req.getServletContext();//固定用法
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(servletContext);
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCharacterEncoding("utf-8");
        resolver.setPrefix("/WEB-INF/templates/");
        resolver.setSuffix(".html");
        resolver.setCacheable(false);

        //3.关联解析器到引擎对象上
        engine.setTemplateResolver(resolver);

        //4.提供给模板引擎本次解析的上下文对象
        WebContext webContext=new WebContext(req,resp,servletContext);

        //5.准备好要放入的Context数据
        List<String> courseList=getCoursrList();
        webContext.setVariable("courseList",courseList);

        //6.通过模板引擎生成的最终的正文内容
        String responseBody=engine.process("course-list",webContext);

        //7.填充响应对象
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        resp.getWriter().println(responseBody);

    }

    private List<String> getCoursrList() {
        return Arrays.asList("JavaSE","JavaDS","JavaDB","JavaWeb","JavaTest","JavaEE");
    }
}

<!doctype html>
<html lang="zh-hans" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>课程列表</title>
</head>
<body>
  <h1>计算机专业的课程列表</h1>
  <ol>
      <li th:each="course : ${courseList}" th:text="${course}"></li>
  </ol>
</body>
</html>

在这里插入图片描述

注意:

  1. Resolver对象和Context对象使用正确
  2. 模板文件放对位置
  3. 模板文件不是 web 资源(不能访问)

各个对象的生命周期:(最有效率的)
在这里插入图片描述

监听器

  • 在 Servlet 运行过程中, 会有一些特殊的 “时机”, 可以供我们来执行一些我们自定义的逻辑. 监听器就是让程序猿可以在这些特殊时机 “插入代码”.
  • 监听器(listen) 模式 <-> 事件驱动的Java版本
    场景:注册用户
    注册用户 -> 发送新用户奖励 -> 根据用户的不同地域生成不同的标签 -> 给用户发送成功通知…
    在这里插入图片描述
    监听上述操作 —监听器(listener)

如何编写代码在合适的时机,进行模板对象和解析对象的构建

  • 希望在ServletContext刚被初始化好的时机下,执行我们的模板初始化工作
    由于ServletContext只会被初始化一次,所以,我们的模板初始化工作也只有一次 举例:
    在店铺刚开张的时候,执行模板初识化工作
    由于店铺只会开张一次,所以模板只会初始化一次
    以后每次卖商品时,直接使用开店时,初始化好的模板对象就可以了

  • Servlet标准提供方法,可以在ServletContext初始好后执行我们的代码
    1. 添加@WebListener,代表我们写的类是一个监听器类
    2. 实现ServletContextListener接口,我们关心的ServletContext初始化销毁的事件
    3. 重写contextlnitialized方法,在ServletContext初始化好后执行一些代码

在这里插入图片描述
引擎对象怎么传递过来?
看到ServletContext是不是同一个对象,把引擎对象放到ServletContext对象中来传递

@WebListener
public class ThymeleafConfig implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        //1.创建一个模板引擎对象
        TemplateEngine engine=new TemplateEngine();

        //2.创建一个解析器对象
        ServletContext servletContext = sce.getServletContext();//固定用法
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(servletContext);
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCharacterEncoding("utf-8");
        resolver.setPrefix("/WEB-INF/templates/");
        resolver.setSuffix(".html");
        resolver.setCacheable(false);

        //3.关联解析器到引擎对象上
        engine.setTemplateResolver(resolver);

        //3.5把引擎对象放进 ServletContext中
        servletContext.setAttribute("engine",engine);
    }

    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

@WebServlet("/template")
public class TemplateServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = req.getServletContext();
        //4.提供给模板引擎本次解析的上下文对象
        WebContext webContext=new WebContext(req,resp,servletContext);

        //5.准备好要放入的Context数据
        List<String> courseList=getCoursrList();
        webContext.setVariable("courseList",courseList);

        //6.通过模板引擎生成的最终的正文内容
        //3.5从ServletContext对象中取出之前放进去的engine
        TemplateEngine engine=(TemplateEngine)servletContext.getAttribute("engine");
        String responseBody=engine.process("course-list",webContext);

        //7.填充响应对象
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html");
        resp.getWriter().println(responseBody);
    }
    private List<String> getCoursrList() {
        return Arrays.asList("JavaSE","JavaDS","JavaDB","JavaWeb","JavaTest","JavaEE");
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值