渲染就是把数据和页面进行结合起来, 主要分为服务器渲染和客户端渲染两种方式. 如下图所示:
服务器渲染指的是数据和页面的结合工作由服务器来完成;
客户端渲染指的是服务器将数据返回给浏览器,由浏览器将数据和页面进行结合, 通常是用 ajax 进行交互.
简单说一下其弊端,例如用字符串来拼接一个 html 页面,如下所示:
@WebServlet("/html")
public class HtmlServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String sex = req.getParameter("sex");
String nickname = req.getParameter("nickname");
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().write(" name: "
+ name + ""
);
resp.getWriter().write(" sex: "
+ sex + ""
);
resp.getWriter().write(" nickname: "
+ nickname + ""
);
}
}
通过 query string 来写入参数传过来后, 返回的页面中就包含了 query string 中的值.但是我们再看这段代码,非常简单地界面还可以,稍微复杂点的界面想要通过这种方式来实现就会特别麻烦,例如像 CSDN 我们点开的任何一个页面,于是就有了模板引擎的出现.
模板引擎指的是我们单独写一个固定的 html 页面, 这里写好之后就固定不动了, 然后不固定的,动态变化的字段使用特殊符号进行占位, 当程序跑起来后, 不固定的地方得以替换. 例如 印象笔记这个软件就有模板这个功能, 我们在使用这个模板的时候, 只需要往里面套文字即可, 大大减少了使用者的工作量, 非常便捷, 那么模板引擎就有这样的功能.
Java 模板引擎非常之多, 但大都大同小异, 这里我们以 Thymeleaf 为例进行简单演示使用流程.
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=\, initial-scale=1.0">
<title>电话本title>
head>
<body>
<ul>
<li th:each="person : ${persons}">
<span th:text="${person.name}">span>
<span th:text="${person.phone}">span>
li>
ul>
body>
html>
代码解读:
th: 就是 thymeleaf 的缩写, 指的是这个属性由 thymeleaf 来提供;
${person.name}: 这就是一个具体的变量, 也就是上文中所说的不固定的部分, 就可以实现动态的变换.
@WebListener
public class ThymeleafConfig implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
// 初始化 TemplateEngine
ServletContext context = servletContextEvent.getServletContext();
// 1. 创建 engine 实例
TemplateEngine engine = new TemplateEngine();
// 2. 创建 resolver 实例
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(context);
resolver.setPrefix("/WEB-INF/template/");
resolver.setSuffix(".html");
resolver.setCharacterEncoding("utf-8");
// 将 engine 和 resolver 关联起来
engine.setTemplateResolver(resolver);
// 3. 把创建好的 engine 实例给放到 ServletContext 中
context.setAttribute("engine",engine);
System.out.println("TemplateEngine 初始化完毕!");
}
}
代码解读:
@WebListener: 加这个目的是为了让 Tomcat 能够识别到这个类;
TemplateEngine: Template 模板的意思, Engine 引擎的意思; 这个类是 Thymeleaf 的核心类, 用于完成最终页面的渲染工作;
ServletContextTemplateResolver: 创建一个模板解析器对象, 搭配 ServletContext 来使用, 也就是将之前写好的 HTML 模板加载过来, 并告知 engine;
总之, ServletContext 创建的对象存在的意义就是多个 Servlet 之间能够共享数据; 关于 ServletContext 的使用如下:
- void setAttribute(String name, Object obj): 设置属性(键值对);
- Object getAttribute(String name): 根据属性名获取属性值, 如果那么不存在就返回 null;
- void removeAttribute(String name): 删除对应的属性.
class Person {
public String name;
public String phone;
public Person(String name, String phone) {
this.name = name;
this.phone = phone;
}
}
@WebServlet("/each")
public class EachServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
List<Person> persons = new ArrayList<>();
persons.add(new Person("Lee", "110"));
persons.add(new Person("Mee", "111"));
persons.add(new Person("Nee", "112"));
WebContext webContext = new WebContext(req,resp,getServletContext());
webContext.setVariable("persons", persons);
// 初始化模板引擎
TemplateEngine engine = (TemplateEngine) getServletContext().getAttribute("engine");
String html = engine.process("thymeleafEach", webContext);
resp.getWriter().write(html);
}
}
代码解读:
WebContext: WebContext 对象里面主要包含要渲染的变量有哪些, 以及变量的值是什么; 就是一个键值对结构, 目的是将 ${persons} 与 java 中的 persons 关联起来, 将模板中的 persons 变量渲染成 persons 的值; 也就是将 HTML 模板中的变量和 java 代码中的变量给关联起来;
engine.process(“thymeleafEach”, webContext):
总结 模板引擎 的使用流程: