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 Html web page code (this is the advantage of the template engine compared with the Servlet directly returning to the dynamic page)
Principle / process
Thymeleaf usage process
Thymeleaf is a template engine in Java, which is the most popular one at present
1. Introduce dependency through maven
stay maven central warehouse Search Thymeleaf
Select 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 introducing 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, put it in webapp / WEB-INF / templates directory
<h3 th:text="${message}"></h3>
give an example:
<body> <h3>Web template technology learning</h3> <p th:text="${message}"></p> </body>
You will find that there is red:
th:text is the syntax of Thymeleaf, and the browser cannot directly recognize the th:text attribute
3. Write Servlet code
- Create a template engine and a web page template parser
- Set render time encoding
- Set the prefix and suffix of web page template file and path
- Bind the template parser to the template engine
- Create a web context (the semantics of the environment, which contains the map structure and stores key value pair data)
- Set data of key value pair
- Returns the rendered web page string to the response body
@WebServlet("/hello") public class helloServlet extends HttpServlet { // Generally, the url is entered in the browser address bar to access the web page, which is the get method // All template engines return html, so override doGet @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8"); // Using thymeleaf template technology // Create a template engine TemplateEngine engine = new TemplateEngine(); // Create a parser for the web page template: getServletContext() is a method in HttpServlet that returns the Servlet context object ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(getServletContext()); // Sets the encoding at render time resolver.setCharacterEncoding("utf-8"); // Set the prefix and suffix of web page template file and path resolver.setPrefix("/WEB-INF/templates/"); // prefix resolver.setSuffix(".html"); // suffix // Bind the template parser to the template engine engine.setTemplateResolver(resolver); // Create a web context (the semantics of the environment, in which there is a map structure that can store the data of key value pairs) WebContext webContext = new WebContext(req,resp,getServletContext()); // Set a key value pair data, which can be understood as: define a variable for the web page template, the variable name is message, and the value is "hello template engine" // queryString pass in msg=xxx webContext.setVariable("message",req.getParameter("msg")); // The template engine renders the web page template: the first parameter is the template name, and the second parameter is the Web context (in which the data is saved) // According to the prefix + template name + suffix set by the template parser For the template path, find the template, and then organize the template content + data // The return value is the rendered web page string String html = engine.process("hello",webContext); resp.getWriter().write(html); } }
Start the service and refresh the page:
Each request creates a template engine and a web page template parser, which is inefficient and unnecessary. We can rewrite an init method because init only executes once, while doGet method executes every request. You can put the code for creating template engine and web page template parser into init method
@Override public void init() throws ServletException { // Create a template engine TemplateEngine engine = new TemplateEngine(); // Create a parser for the web page template: getServletContext() is a method in HttpServlet that returns the Servlet context object ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(getServletContext()); // Sets the encoding at render time resolver.setCharacterEncoding("utf-8"); // Set the prefix and suffix of web page template file and path resolver.setPrefix("/WEB-INF/templates/"); // prefix resolver.setSuffix(".html"); // suffix // Bind the template parser to the template engine engine.setTemplateResolver(resolver); }
However, at this time, you will find that the code will be red:
Set templateengine = new templateengine(); Put it outside the init() method, i.e
Restart, refresh page:
(efficiency improved)
Thymeleaf common template syntax
command | function |
---|---|
th: text | The text content of the expression evaluation result is displayed in the label body |
th: [HTML tag attribute] | Set the value of any HTML tag attribute |
th: if | When the result of the expression is true, the content will be displayed; otherwise, it will not be displayed |
th: each | Circular access element |
${variable name} to refer to the key value pair data set in Java code (${key} is the value)
Note: the absolute path of the website still needs to add http: / /, which needs to be written in full
give an example:
webContext.setVariable("a1","http://www.baidu.com");
Understand that only one engine instance 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: objects and attributes will not change). In the previous part of the article, an improved method is also proposed, which is put in the init() method of Servlet
But there are still problems: each Servlet needs to be created in the init method. In a webapp, there are still many engine and resolver objects
Each Servlet class that needs to render a page needs to create a TemplateEngine instance and initialize it. In fact, it is completely unnecessary!
In a complete project, you only need to create a TemplateEngine and initialize it only once
In order to improve the above problems, ① ServletContext and ② "listener" in Servlet need to be used
ServletContext
ServletContext is a global information storage space in the Servlet program. The server exists from the beginning and is destroyed only after the server is shut down
As shown in the following figure:
- When Tomcat starts, it will create a corresponding ServletContext for each webapp
- All servlets in a Web application share the same Servlet Context object
- You can use httpservlet Getservletcontext() or HttpServletRequest Getservletcontext() gets the ServletContext object of the current webapp
Understanding Context: Context / environment; It is often used to set some data into the Context; Objects in the Context can refer to each other's data (Context is a semantic concept in many places)
Namely:
Data cannot be transferred directly between multiple servlets, but some data can be set / used through a shared context (data transfer)
ServletContext is similar to Map structure, which stores multiple sets of key value pair data
Important methods of ServletContext object
method | describe |
---|---|
void setAttribute(String name, Objectobj) | Set properties (key value pairs) |
Object getAttribute(String name) | Get the property value according to the property name. If the name does not exist, return null |
void removeAttribute(String name) | Delete the corresponding attribute |
You can see that Servlet Context is very similar to HttpSession class. It also organizes several key value pair structures internally, which is equivalent to a hash table; At this time, multiple servlets can share the same data through webcontext
Code example: multiple servlets share data
1) Create 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"); // Write data to the context of Servlet sharing ServletContext sc = getServletContext(); sc.setAttribute("d",data); resp.setContentType("text/html;charset=utf-8"); resp.getWriter().write("write in Context success!"); } }
2) Create ContextReadServlet class
@WebServlet("/read") public class ContextReadServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Write data to the context of Servlet sharing ServletContext sc = getServletContext(); Object data = sc.getAttribute("d"); resp.setContentType("text/html;charset=utf-8"); resp.getWriter().write("read Context:" + data); } }
Start the service and open the page:
If we do not access / write but directly access / read, the data obtained at this time is null:
Listener listener
A listener belongs to a design mode
For example, as I learned earlier, in html / js, bind an event (event registration) for a DOM element. There is no need to call the function of the event manually, but the browser calls the function bound by the event when the event occurs
This "event" is actually the design pattern of the listener
If it is a code with strong coupling, we may execute it; The above example is the code to be executed when an event occurs, which is decoupled from the event occurrence
During the operation of Servlet, there will be some special "opportunities" for us to execute some custom logic
The listener is to allow the program ape to "insert code" at these special times
Summary of listener advantages:
- Decouple the event and the code to be executed after the event
- Register a function or method to the listener in advance and execute it automatically after an event occurs
Code example: listen for the creation of ServletContext
Steps:
- First create a class
- Add @ WebListener annotation modification, otherwise Tomcat cannot 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) { // This will be called when the context is created // The creation time is before all servlets are instantiated } @Override public void contextDestroyed(ServletContextEvent sce) { // This will be called when the context is destroyed } }