Article directory
1. Server Rendering vs Client Rendering
There are two ways for the server to generate dynamic pages: 服务器渲染
and客户端渲染
server rendering
Features:
- The server will return a
完整的 html 页面
- Some dynamically changing data in html are
模板引擎
dynamically replaced by " "
advantage:
- 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:
- 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:
- Also known as the way the
前后端分离
clientajax
interacts with the server- What the server returns is just simple data, and most of the data
JSON
is organized in the form of
advantage:
- 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:
- 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:
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
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 result
can 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
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
}
- 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)- When the servlet is loaded, the method will be called once
init()
, and the initialization of Thymeleaf should be placed in the init() method- Create an
ServletContextTemplateResolver
object . resolver: the resolver. The function of this object is to load the html template file from disk. The following parametersgetServletContext()
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.- Next, set some properties for the resolver object.
setPrefix()
andsetSuffix()
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- Associate the parser object with the
TemplateEngine
object . 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());
}
- 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.
- 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>
. oneengine.process
to perform specific rendering work. This operation associates the specific template file
with the data to be rendered, and writes the final result to theresp
object . The first parameter is the file name of the html template, and the last two parameters are unchanged.
result:
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!