Lesson11:模板引擎

目录

一、页面的渲染方式 

1.1 页面分类

2.2 如何生成一个动态页面

2.2.1 服务器渲染

2.2.2 客户端渲染(前后端分离)

二、猜数字实例(没有模板引擎)

2.1 前端代码

2.2 后端代码

三、猜数字实例(使用模板引擎)

3.1 引入依赖(3.0.12)

3.2 编写模板文件(将需要动态替换的数据用占位符号进行占位)

3.3 将模板放在特殊的目录下

3.4  编写Servlet代码

3.4.1 Thymeleaf的初始化

3.4.2 进行模板渲染

3.5 总结

四、表白墙实例(使用模板引擎)

4.1 创建maven工程项目文件

4.2 引入依赖 

4.3 新建文件夹

4.4 配置tomcat和验证

4.5 写代码

4.5.1 操作数据库

4.5.2 前端代码

4.5.3 后端代码

总结


一、页面的渲染方式 

1.1 页面分类

一个不变的页面,称为静态页面。
一个随着用户输入的不同,产生不同结果的页面,称为动态页面。

2.2 如何生成一个动态页面

2.2.1 服务器渲染

特点:①服务器返回一个完整的html页面。②html页面上的一些动态的数据,往往是通过模板引擎的方式进行动态替换的。

模板引擎:就是一个HTML,在这个HTML中将一些动态变化的数据挖空,用特殊符号占个位置,后面通过这些代码把空给补上。模板引擎就是在填空。

优点:前后端交互的次数比较少。(一次HTTP请求、响应,就能拿到一个完整的页面),比较高效。

缺点:前端代码和后端代码不能充分解耦合。前端开发人员和后端开发,很难进行一个明确的分工,同时也不能各自独立进行测试。

2.2.2 客户端渲染(前后端分离)

特点:客户端通过ajax的方式和服务器进行交互。②服务器返回的不是完整的html,通常只是纯粹的数据.这些数据常见的是以json的方式来组织的

优点:能够让前后端进行充分的解耦.前端开发人员和后端开发人员各自开发,相互之间不干扰,并且也能各自分别进行测试。(后端的测试::Postman。前端的测试:使用mock server)
缺点: 前后端交互的次数比较多(页面中可能需要通过多组ajax来获取到完整的数据,效率比较低)

二、猜数字实例(没有模板引擎)

2.1 前端代码

<!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>
    <div>
        <form action="guess" method="post">
            <input type="text" name="inputNum">
            <input type="submit" value="提交">
        </form>
    </div>
    <div>
        结果:
    </div>
</body>
</html>

2.2 后端代码

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Random;

@WebServlet("/guess")
public class GuessNumServlet extends HttpServlet {
    Random random = new Random();
    int num = random.nextInt(100)+1;
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int guessNum = Integer.parseInt(req.getParameter("inputNum"));
        String result = null;
        if(num > guessNum){
            result = "猜小了";
        }else if(num < guessNum){
            result = "猜大了";
        }else {
            result = "猜对了";
        }
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().write("<!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" +
                "    <div>\n" +
                "        <form action=\"guess\" method=\"post\">\n" +
                "            <input type=\"text\" name=\"inputNum\">\n" +
                "            <input type=\"submit\" value=\"提交\">\n" +
                "        </form>\n" +
                "    </div>\n" +
                "    <div>\n" +
                "        结果:\n" + result +
                "    </div>\n" +
                "</body>\n" +
                "</html>");
    }
}

如果不采用模板引擎,在Java代码中通过拼装字符串的方式返回HTML,不仅将业务逻辑的代码和用户界面的代码混在一起,非常不友好。同时也非常容易出错。

三、猜数字实例(使用模板引擎)

Java的模板引擎很多,Thymeleaf是Spring官方推荐的模板引擎,因此,本文使用的是ThymeLeaf。

3.1 引入依赖(3.0.12)

        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>

3.2 编写模板文件(将需要动态替换的数据用占位符号进行占位)

<!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>
    <div>
        <form action="guess" method="post">
            <input type="text" name="inputNum">
            <input type="submit" value="提交">
        </form>
    </div>
    <div>
        结果:
        <span th:text="${result}"></span>
    </div>
</body>
</html>

实际上,Thymeleaf相当于对HTML的语法进行了扩充。正常的HTML是没有th:text这个属性的,是Thymeleaf扩充的。一旦Thymeleaf看到这个符号,就会知道这是一个需要被替换的部分。${result}相当于在模板引擎中定义的变量,可以在Java代码中对这个变量进行赋值

3.3 将模板放在特殊的目录下

WEB-INF ——》template——》.html模板文件

3.4  编写Servlet代码

3.4.1 Thymeleaf的初始化

[1].  创建一个模板引擎对象engine

[2].  因为Servlet被加载的时候,会调用init方法,将Thymeleaf的初始化放在这里很适合。

1)    重写init()方法

2)    创建一个ServletContextTemplateResolver对象resolver,从磁盘上加载模板引擎文件

3)    把engine和resolver关联起来

 // 1.创建一个模板引擎对象
    private TemplateEngine engine = new TemplateEngine();
    // 2.因为servlet被加载的时候,会调用init方法,所以Thymeleaf的初始化就很适合放在这里
    @Override
    public void init() throws ServletException {
        // 2.1 创建一个ServletContextTemplateResolver对象,功能就是从磁盘上加载模板引擎文件
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(getServletContext());
        //2.2 对resolver对象设置一些属性 加载 /WEB-INF/template/ 目录中, 以 .html 结尾的文件, 作为模板引擎
        resolver.setPrefix("/WEB-INF/template/");
        resolver.setSuffix(".html");
        resolver.setCharacterEncoding("utf-8");
        // 2.4 把resolver和engine关联起来
        engine.setTemplateResolver(resolver);
    }

3.4.2 进行模板渲染


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        // 通过模板引擎加载html文件
        WebContext webContext = new WebContext(req,resp,getServletContext());
        // 针对猜数字的初始页面,不需要替换内容,直接往下写
        engine.process("guessNum",webContext, resp.getWriter());
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        int guessNum = Integer.parseInt(req.getParameter("inputNum"));
        String result = "";
        if (num < guessNum) {
            result = "猜高了";
        } else if (num > guessNum) {
            result = "猜低了";
        } else {
            result = "猜对了";
        }
        WebContext webContext = new WebContext(req,resp,getServletContext());
        webContext.setVariable("result",result);
        engine.process("guessNum",webContext, resp.getWriter());
    }

3.5 总结

TemplateEngine:表示一个模板引擎对象,功能是进行页面渲染。核心方法是process。

ServletContextTemplateEngine:解析器对象,用来加载模板文件,指定模板的位置。

WebContext:就是一个键值对结构,功能是把html中的占位符和具体的Java变量关联起来。

ServletContext:上下文对象,每个webapp都有一个上下文对象,p有多个servlet,这多个servlet之间可以共享ServletContext对象。可以基于这个ServletContext对象在多个Servlet之间传递数据。

四、表白墙实例(使用模板引擎)

4.1 创建maven工程项目文件

4.2 引入依赖 

    <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/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.25</version>
        </dependency>
    </dependencies>

4.3 新建文件夹

其中,MessageWall.html就是模板文件。

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <display-name>Archetype Created Web Application</display-name>
</web-app>

4.4 配置tomcat和验证

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("hello");
    }
}

在浏览器窗口输入:http://127.0.0.1:8080/MessageWallTemplate/hello可以显示出hello就证明没问题。

4.5 写代码

4.5.1 操作数据库

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBUTil {
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/messagewall?characterEncoding=utf8&useSSL=false";
    private static final String username = "root";
    private static final String password = "1111";
    private static DataSource dataSource = new MysqlDataSource();
    static {
        ((MysqlDataSource)dataSource).setURL(URL);
        ((MysqlDataSource)dataSource).setUser(username);
        ((MysqlDataSource)dataSource).setPassword(password);
    }
    public Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    public void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
        if(resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

4.5.2 前端代码

<!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>表白墙</title>
</head>
<body>
    <style>
        /* 清空浏览器默认样式 */
        * {
            margin: none;
            padding: none;
            box-sizing: border-box;
        }
        .container {
            width: 300px;
            /* 水平居中 */
            margin: 0 auto;
        }
        h3 {
            text-align: center;
            padding: 10px 0;
        }
        p {
            text-align: center;
            font-size: 15px;
            color: rgb(196, 180, 159);
        }
        .row {
            display: flex;
            width: 100%;
            font-size: 18px;
            justify-content: center;
            align-items: center;
            height: 40px;
        }
        .edit {
            margin: 2px 0;
            height: 38px;
            width: 200px;
        }
        span {
            width: calc(100% - 200px);
        }
        .submit {
            width: 300px;
            height: 35px;
            background-color: pink;
            color: azure;
            font-size: 20px;
            border-radius: 3px;
            border: 0;
        }
        .submit:active {
            background-color: green;
        }
    
    </style>
    <!-- 给外层加个容器,通过这个容器实现对齐的效果 -->
    <div class="container">
        <h3>表白墙</h3>
        <p>输入后点击提交,会将信息显示在表格中</p>  
        <form action="message" method="post">
            <div class="row">
                <span>谁:</span>
                <input type="text" class="edit" id="name1" name="from">
            </div>
            <div class="row">
                <span>对谁:</span>
                <input type="text" class="edit" id="name2" name="to">
            </div>
            <div class="row">
                <span>说什么:</span>
                <input type="text" class="edit" id="message" name="message">
            </div>
            <div class="row">
                <input type="submit" value="提交" class="submit">
            </div> 
        </form>
        <!-- 接下来的div就通过循环的方式,来获取到内容 -->
        <div class="row" th:each="message:${messages}">
            <span th:text="${message.from}"></span>
            对
            <span th:text="${message.to}"></span>
            说:
            <span th:text="${message.message}"></span>
        </div>
    </div>
</body>
</html>

4.5.3 后端代码

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;


@WebServlet("/message")
public class MessageWallTemplate extends HttpServlet {
    // 1.创建一个模板引擎对象
    private TemplateEngine engine = new TemplateEngine();
    // 2.因为servlet被加载的时候,会调用init方法,所以Thymeleaf的初始化就很适合放在这里
    @Override
    public void init() throws ServletException {
        // 2.1 创建一个ServletContextTemplateResolver对象,功能就是从磁盘上加载模板引擎文件
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(getServletContext());
        //2.2 对resolver对象设置一些属性 加载 /WEB-INF/template/ 目录中, 以 .html 结尾的文件, 作为模板引擎
        resolver.setPrefix("/WEB-INF/template/");
        resolver.setSuffix(".html");
        resolver.setCharacterEncoding("utf-8");
        // 2.4 把resolver和engine关联起来
        engine.setTemplateResolver(resolver);
    }
    private static List<Message> messages = new ArrayList<>();
    // 返回所有的留言
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        // 从数据库中读出所有数据
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        DBUTil dbuTil = new DBUTil();
        try {
            connection = dbuTil.getConnection();
            String sql = "select * from message";
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                Message message = new Message();
                message.from = resultSet.getString("from");
                message.to = resultSet.getString("to");
                message.message = resultSet.getString("message");
                messages.add(message);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbuTil.close(connection,statement,resultSet);
        }
        // 渲染模板
        WebContext webContext = new WebContext(req,resp,getServletContext());
        webContext.setVariable("messages",messages);
        engine.process("MessageWall",webContext, resp.getWriter());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 请求的body中可能包含中文,设置一下编码格式
        // 从请求中拿到数据
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        Message message = new Message();
        message.from = req.getParameter("from");
        message.to = req.getParameter("to");
        message.message = req.getParameter("message");
        // 写到数据库中
        Connection connection = null;
        PreparedStatement statement = null;
        DBUTil dbuTil = new DBUTil();
        try {
            connection = dbuTil.getConnection();
            String sql = "insert into message values(?,?,?)";
            statement = connection.prepareStatement(sql);
            statement.setString(1,message.from);
            statement.setString(2,message.to);
            statement.setString(3,message.message);
            statement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbuTil.close(connection,statement,null);
        }
        messages.add(message);
        // 渲染模板
        WebContext webContext = new WebContext(req,resp,getServletContext());
        webContext.setVariable("messages",messages);
        engine.process("MessageWall",webContext, resp.getWriter());

    }
}
class Message{
    public String from;
    public String to;
    public String message;
}

总结

setp1:写好前端模板

step2:初始化thymeleaf模板

          创建WEB-INF—》template—》的目录结果,将前端模板拷入该目录下。

          复制初始化代码

step3:渲染模板

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘减减

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值