Knowledge of template engines

1. Server Rendering vs Client Rendering

There are two ways for the server to generate dynamic pages: 服务器渲染and客户端渲染

server rendering

Features:

  1. The server will return a完整的 html 页面
  2. Some dynamically changing data in html are 模板引擎dynamically replaced by " "

advantage:

  1. The number of front-end and back-end interactions is small, and a complete html file can be obtained with one HTTP request/response, which is highly efficient

shortcoming:

  1. Front-end and back-end code 无法充分解耦combined. In formal work, this method is rarely used, and requires front-end and back-end developers to cooperate in development. The division of labor is not clear enough, and there is no way to test independently.

client-side rendering

Features:

  1. Also known as the way the 前后端分离client ajaxinteracts with the server
  2. What the server returns is just simple data, and most of the data JSONis organized in the form of

advantage:

  1. Front-end and back-end code 充分解耦合. Front-end and back-end developers can develop their own and test their code through some testing tools (such as Postman on the back-end, mock server on the front-end)

shortcoming:

  1. The number of front-end and back-end interactions is large, and multiple groups of ajax are required to obtain a complete data. Compared with server rendering, the efficiency is lower, but because of its advantages, this disadvantage is not a big deal.

2. Simple Number Guessing Game for Server Edition

2.1 No template engine

If there is no template and you want the server to return a complete html, the only way is to write the html code on the web page in the data format through resp.getWriter().write() “text/html;charset=utf-8”, and pass the data that needs to be dynamically transformed through 字符串拼接the method.

//html 代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="guess" method="post"> 
        <input type="text" name="Num">
        <input type="submit" value="猜">
        <div>
            结果:
        </div>
    </form>
</body>
</html>

The core code is actually only the part of the form in the body tag, but the entire html code is still relatively large (relatively speaking)

// Servlet 程序
@WebServlet("/guess")
public class GuessNumber extends HttpServlet {
    
    
    private int toGuess = 0;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.setContentType("text/html;charset=utf8");
        Random random = new Random();
        toGuess = random.nextInt(100)+1;
        System.out.println("toGuess=" + toGuess);
        String html = "<!DOCTYPE html>\n" +
                "<html lang=\"en\">\n" +
                "<head>\n" +
                "    <meta charset=\"UTF-8\">\n" +
                "    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n" +
                "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +
                "    <title>Document</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "    <form action=\"guess\" method=\"post\">\n" +
                "        <input type=\"text\" name=\"Num\">\n" +
                "        <input type=\"submit\" value=\"猜\">\n" +
                "        <div>\n" +
                "            结果:\n" +
                "        </div>\n" +
                "    </form>\n" +
                "</body>\n" +
                "</html>";
        resp.getWriter().write(html);//返回原始猜数字页面
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.setContentType("text/html;charset=utf8");
        int num = Integer.parseInt(req.getParameter("Num"));
        String str = ""; //结果直接拼接在要输出的 html 代码中
        if(num < toGuess) {
    
    
            str = "猜小了";
        }else if (num > toGuess) {
    
    
            str = "猜大了";
        }else {
    
    
            str = "猜对了";
        }
        String html = "<!DOCTYPE html>\n" +
                "<html lang=\"en\">\n" +
                "<head>\n" +
                "    <meta charset=\"UTF-8\">\n" +
                "    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n" +
                "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +
                "    <title>Document</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "    <form action=\"guess\" method=\"post\">\n" +
                "        <input type=\"text\" name=\"Num\">\n" +
                "        <input type=\"submit\" value=\"猜\">\n" +
                "        <div>\n" +
                "            结果:\n" + str +
                "        </div>\n" +
                "    </form>\n" +
                "</body>\n" +
                "</html>";
        resp.getWriter().write(html);
    }
}

It is obvious that when there is no template engine, the long html code and java code are mixed together, which looks extremely inconvenient

2.2 Template engine application (guess the number)

The template engine, as its name suggests, is a template, which deducts the part to be dynamically replaced, and uses it 特殊符号as a placeholder. This template can be used back in the Servlet code to replace the content to be replaced.

Similar to:

insert image description here

A blank panda head is a template. On this basis, you can directly add a panda face and text to complete a panda head emoticon package, instead of creating an emoticon package from scratch every time.

There are many template engines, this time the one used isThymeleaf

step one:

Create a project, the directory structure and the like will not be introduced, please see the link for details

Details

Step 2:

To introduce dependencies, you need to introduce two dependencies, one is Servlet, the other is Thymeleaf, search for these two keywords in the central warehouse, the first is to select the appropriate version, copy the code snippets topom.xml

<dependencies>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf</artifactId>
        <version>3.0.15.RELEASE</version>
    </dependency>
</dependencies>

Step 3:

Write a template file and modify the above html code for guessing numbers, specifically, place the information that needs to be dynamically replaced with special symbols

<body>
    <form action="guess" method="post">
        <input type="text" name="Num">
        <input type="submit" value="">
    </form>
    <div>
        结果:<span th:text="${result}"></span>
    </div>
</body>

The only thing that needs to be dynamically replaced here is the result displayed here, which th:text="${result}is equivalent to the variable defined in the template engine. The variable defined here is the variable that resultcan be assigned in the java code when you go back, so as to achieve the result of dynamic replacement.

For normal html code, there is no such attribute as th:text, that is Thymeleaf 扩充的属性, when it sees this attribute, it knows that there is a part that needs to be replaced.

Put the modified template file in a special directory

insert image description here

Step 4:

Write the servlet code

(1) Thymeleaf 进行初始化For, the initialization code is a fixed routine, it is recommended to save it where, and copy and paste it directly when you use it

private TemplateEngine engine = new TemplateEngine();//1

@Override
public void init() throws ServletException {
    
    
    ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(getServletContext());//3
    resolver.setPrefix("/WEB-INF/template/");//4
    resolver.setSuffix(".html");//4
    resolver.setCharacterEncoding("utf-8");
    engine.setTemplateResolver(resolver);//5
}
  1. First create one TemplateEngine 对象, Template: template, Engine: engine. This class is the core class of Thymeleaf, used to complete the final page rendering work (replace data)
  2. When the servlet is loaded, the method will be called once init(), and the initialization of Thymeleaf should be placed in the init() method
  3. Create an ServletContextTemplateResolverobject . resolver: the resolver. The function of this object is to load the html template file from disk. The following parameters getServletContext()are obtained 上下文对象. Each webapp has its own context object (ServletContext), which is shared by all servlets in the current webapp. Data can be transferred between multiple servlets based on this.
  4. Next, set some properties for the resolver object. setPrefix()and setSuffix()to specify which files are considered as template files and need to be loaded, the former is the file prefix and the latter is the file suffix. Pay attention to the writing method, the loading directory cannot be missing a '/'. setCharacterEncoding()set character set
  5. Associate the parser object with the TemplateEngineobject . Later TemplateEngine will perform specific rendering. When working, you need to get the template just parsed first.

(2) Template rendering specific operations

private int toGuess = 0; //需要被猜的数据
//处理 GET 请求操作,包含着生成随机数,以及返回猜数字原始页面
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    resp.setContentType("text/html;charset=utf-8");
    Random random = new Random();
    toGuess = random.nextInt(100)+1;
    System.out.println("toGuess = " + toGuess);
    WebContext webContext = new WebContext(req,resp,getServletContext());
    engine.process("GuessNum",webContext,resp.getWriter());
}
//处理 POST 请求,获取的 body 中的数据和 toGuess 进行比较,将结果替换到模板中 
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    resp.setContentType("text/html;charset=utf-8");
    int num = Integer.parseInt(req.getParameter("Num"));
    String result = "";
    if(num < toGuess) {
    
    
        result = "猜低了";
    }else if (num > toGuess) {
    
    
        result = "猜高了";
    }else {
    
    
        result = "猜对了";
    }
    WebContext webContext = new WebContext(req,resp,getServletContext());
    webContext.setVariable("result",result);
    //前面的"result"与th:text="${result}"中的要被替换的数据名相对应
    engine.process("GuessNum",webContext, resp.getWriter());
}
  1. The WebContext object is used to organize the data to be rendered, which is actually a key-value pair structure (hash table), remember the three parameters in it.
  2. Insert key-value pairs into the hash table through the setVariable()method , there can be multiple placeholders in each template, and multiple variables can be set through this method. In processing the POST request, the generated result needs to be filled into the html <span th:text="${result}"></span>. one
  3. engine.processto perform specific rendering work. This operation associates the specific template file
    with the data to be rendered, and writes the final result to the respobject . The first parameter is the file name of the html template, and the last two parameters are unchanged.

result:

insert image description here

3. Thymeleaf template syntax

The template commands used in the front are th:text, in fact there are other uses

Order Features
th:text Display the text content of the expression evaluation result in the tag body
th:[HTML tag attribute] Set the value of any HTML tag attribute
th:if Display the content when the result of the expression is true, otherwise do not display
th:each iterate over elements

Set the label text: th:text

Refer to the usage in the previous html template

Set tag attributes: th:[HTML tag attributes]

There is a link in the html template that needs to be replaced

<a th:href="${url}">百度</a>

in servlet code

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

At this point, click on the a tag on the page to jump to Baidu

Conditional judgment: th:if

<div th:if="${!newGame}">
  <div>结果: <span th:text="${result}"></span> </div>
</div>

When newGame is false, it means that there is no need to restart a game, and continue to replace the value of result

Iterating through: th:each

usage:

th:each="自定义的元素变量名称 : ${集合变量名称}" 
<div th:each="message:${messages}">
    <span th:text="${message.from}"></span><span th:text="${message.to}"></span>
    说:
    <span th:text="${message.message}"></span>
</div>

The messages are the objects that need to be replaced. The Collections type is passed in the java code to replace them, and the messages access each element in the messages. The following th:text="${message.XX} corresponds to the various attributes in the message variable that also need to be replaced

Finish!

Guess you like

Origin blog.csdn.net/weixin_46103589/article/details/123792543