Know the template engine - Thymeleaf

What is a template engine?

[Function] The template engine is created to separate the user interface from the business data (content) . It can separate the Servlet Java code and the Html webpage code (this is the advantage of the template engine compared to the Servlet directly returning the dynamic page )

Principle/ Process

insert image description here

Thymeleaf usage process

Thymeleaf is a template engine in Java, currently the most popular one

1. Import dependencies through maven

Search Thymeleaf in the maven central repository

insert image description here

Choose an appropriate version, such as: 3.0.12

<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.12.RELEASE</version>
</dependency>

After importing dependencies, be sure to refresh the Maven panel
Note: web projects need to be packaged in war format—— <packaging>war</packaging>

2. Create HTML template file

Create hello.html and put it in the webapp/WEB-INF/templates directory

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

Example:

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

You will find that there is a fluttering red:

insert image description here
th:text is the grammar of Thymeleaf, and the browser cannot directly recognize the th:text attribute

3. Write Servlet code

  1. Create a template engine and a web template parser
  2. Set render-time encoding
  3. Set the web template file, the prefix and suffix of the path
  4. Bind the template parser to the template engine
  5. Create a web context (the semantics of the environment, which is a map structure, storing key-value pair data)
  6. Set data for key-value pairs
  7. Return the rendered web page string to the response body
@WebServlet("/hello")
public class helloServlet extends HttpServlet {
    
    
    // 一般是浏览器地址栏输入 url 来访问网页,都是get方法
    // 模板引擎都是返回 html,所以重写 doGet
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.setContentType("text/html;charset=utf-8");
        // 使用 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);
        resp.getWriter().write(html);
    }
}

Start the service and refresh the page:

insert image description here

Creating a template engine and a web page template parser for each request is relatively inefficient and unnecessary. We can rewrite an init method, because init is only executed once, and the doGet method is executed every request. The code for creating a template engine and creating a web page template parser is placed in the init method

@Override
public void init() throws ServletException {
    
    
    // 创建一个模板引擎
    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);

}

But at this time, you will find that the code will be red:

insert image description here
Put TemplateEngine engine = new TemplateEngine(); outside the init() method

Reboot, refresh page:
(efficiency improved)

insert image description here

Thymeleaf common template syntax

Order Function
th: text Displays the text content of the expression evaluation result in the tag body
th: [HTML tag attribute] Sets the value of any HTML tag attribute
th: if When the result of the expression is true, the content is displayed, otherwise it is not displayed
th: each loop through elements

${variable name}, to refer to the key-value pair data set in the Java code ( ${key} is the value)

insert image description here

Note: The absolute path of the website still needs to add http://, which needs to be written in full
. Example:

webContext.setVariable("a1","http://www.baidu.com");

Understand that only one instance of the engine is created

The entire web application only needs to be initialized once (the objects engine and resolver in the code only need to be created once)
(reason: the objects and attributes will not change), and in the previous part of the article, an improvement method is also proposed, which is placed in the Servlet's init( ) method

But there are still problems: each Servlet needs to be created in the init method. In a webapp, there are still many engines and resolver objects. Every Servlet class that needs to
render a page needs to create a TemplateEngine instance and initialize it. In fact, there is no such thing at all. necessary!

In a complete project, only one TemplateEngine needs to be created and initialized only once. In
order to improve the above problems, it is necessary to use ①ServletContext and ②"Listener" in Servlet

ServletContext

ServletContext is a global space for storing information in a Servlet program. It exists from the beginning of the server and is destroyed only when the server is closed.

The relationship is as shown in the figure below:
insert image description here

  • When Tomcat starts, it will create a corresponding ServletContext for each webapp.
  • All Servlets in a web application share the same ServletContext object
  • The ServletContext object of the current webapp can be obtained through HttpServlet.getServletContext() or HttpServletRequest.getServletContext()

Understand Context: context/environment; it is often used to set some data into the context environment; objects in the context environment can refer to each other's data (the concept of Context exists in many places, it is a semantic concept)

That is:
between multiple Servlets, data cannot be directly transferred, but some data can be set/used through a shared context (data transfer)
ServletContext is similar to a Map structure, storing multiple sets of key-value pair data

Important methods of the ServletContext object

method describe
void setAttribute(String name, Objectobj) Set properties (key-value pairs)
Object getAttribute(String name) Get the attribute value according to the attribute name, if the name does not exist, return null
void removeAttribute(String name) Delete the corresponding attribute

It can be seen that the ServletContext is very similar to the HttpSession class, and also organizes several key-value pairs internally, which is equivalent to a hash table; at this time, multiple Servlets of the same webapp can share data through ServletContext

Code Example: Multiple Servlets Sharing Data

1) Create the ContextWriteServlet class

@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成功!");
    }
}

2) Create the ContextReadServlet class

@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);
    }
}

Start the service and open the page:

insert image description here

insert image description here

If we do not access /write, directly access /read, then the data obtained at this time is null:

insert image description here

Listener Listener

Listener, which belongs to a design pattern

For example: what I learned earlier, in html/js, to bind an event (event registration) to a DOM element, there is no need to manually call the function of the event, but when the event occurs, the browser will call the event binding The "event" of the specified function
is actually the design pattern of the listener.
If we design it ourselves, it may be: an event occurs, and a piece of code is executed (the coupling is too strong); the above example is the code that needs to be executed when the event occurs, and the event occurs. , two decoupled

During the running of the Servlet, there will be some special "opportunities" for us to execute some custom logic. The
listener is to allow programmers to "insert code" at these special moments.

Summary of the advantages of the listener:

  • Decouple the event from the code that needs to be executed after the event occurs
  • Register a function or method to the listener in advance, and execute it automatically after an event occurs

Code Example: Listening for ServletContext Creation

step:

  • First create a class
  • Add @WebListener annotation modification, otherwise Tomcat will not recognize it
  • Implement the ServletContextListener interface and implement two methods contextInitialized and contextDestroyed
@WebListener
public class MyListener implements ServletContextListener {
    
    
@WebListener
public class MyListener implements ServletContextListener {
    
    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
    
    
        // 这个会在 context 被创建的时候调用.
        // 创建的时机在所有 Servlet 实例化之前.
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    
    
        // 这个会在 context 被销毁的时候调用
    }
}

insert image description here

Guess you like

Origin blog.csdn.net/m0_47988201/article/details/123379401