搭建环境:表述层
2023年11月25日大约 5 分钟约 1019 字
1、视图模板技术 Thymeleaf
①服务器端渲染
②Thymeleaf 简要工作机制
[1]初始化阶段
- 目标:创建 TemplateEngine 对象
- 封装:因为对每一个请求来说,TemplateEngine 对象使用的都是同一个,所以在初始化阶段准备好

[2]请求处理阶段

③逻辑视图与物理视图
假设有下列页面地址:
/WEB-INF/pages/apple.html /WEB-INF/pages/banana.html /WEB-INF/pages/orange.html /WEB-INF/pages/grape.html /WEB-INF/pages/egg.html
这样的地址可以直接访问到页面本身,我们称之为:物理视图。而将物理视图中前面、后面的固定内容抽取出来,让每次请求指定中间变化部分即可,那么中间变化部分就叫:逻辑视图。
④ViewBaseServlet 完整代码
为了简化视图页面处理过程,我们将 Thymeleaf 模板引擎的初始化和请求处理过程封装到一个 Servlet 基类中:ViewBaseServlet。以后负责具体模块业务功能的 Servlet 继承该基类即可直接使用。
public class ViewBaseServlet extends HttpServlet {
private TemplateEngine templateEngine;
@Override
public void init() throws ServletException {
// 1.获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 2.创建Thymeleaf解析器对象
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
// 3.给解析器对象设置参数
// ①HTML是默认模式,明确设置是为了代码更容易理解
templateResolver.setTemplateMode(TemplateMode.HTML);
// ②设置前缀
String viewPrefix = servletContext.getInitParameter("view-prefix");
templateResolver.setPrefix(viewPrefix);
// ③设置后缀
String viewSuffix = servletContext.getInitParameter("view-suffix");
templateResolver.setSuffix(viewSuffix);
// ④设置缓存过期时间(毫秒)
templateResolver.setCacheTTLMs(60000L);
// ⑤设置是否缓存
templateResolver.setCacheable(true);
// ⑥设置服务器端编码方式
templateResolver.setCharacterEncoding("utf-8");
// 4.创建模板引擎对象
templateEngine = new TemplateEngine();
// 5.给模板引擎对象设置模板解析器
templateEngine.setTemplateResolver(templateResolver);
}
protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1.设置响应体内容类型和字符集
resp.setContentType("text/html;charset=UTF-8");
// 2.创建WebContext对象
WebContext webContext = new WebContext(req, resp, getServletContext());
// 3.处理模板数据
templateEngine.process(templateName, webContext, resp.getWriter());
}
}
特别提醒:这个类不需要掌握,因为以后都被框架封装了,我们现在只是暂时用一下。
⑤声明初始化参数

<!-- 配置 Web 应用初始化参数指定视图前缀、后缀 -->
<!--
物理视图举例:/WEB-INF/pages/index.html
对应逻辑视图:index
-->
<context-param>
<param-name>view-prefix</param-name>
<param-value>/WEB-INF/pages/</param-value>
</context-param>
<context-param>
<param-name>view-suffix</param-name>
<param-value>.html</param-value>
</context-param>
⑥Thymeleaf 的页面语法
http://heavy_code_industry.gitee.io/code_heavy_industry/pro001-javaweb/lecture/chapter08/
2、ModelBaseServlet
①提出问题
[1]我们的需求

[2]HttpServlet 的局限
- doGet() 方法:处理 GET 请求
- doPost() 方法:处理 POST 请求
②解决方案
- 每个请求附带一个请求参数,表明自己要调用的目标方法
- Servlet 根据目标方法名通过反射调用目标方法
③ModelBaseServlet 完整代码
特别提醒:为了配合 TransactionFilter 实现事务控制,捕获的异常必须抛出。
public class ModelBaseServlet extends ViewBaseServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 在doGet()方法中调用doPost()方法,这样就可以在doPost()方法中集中处理所有请求
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.在所有request.getParameter()前面设置解析请求体的字符集
request.setCharacterEncoding("UTF-8");
// 2.从请求参数中获取method对应的数据
String method = request.getParameter("method");
// 3.通过反射调用method对应的方法
// ①获取Class对象
Class<? extends ModelBaseServlet> clazz = this.getClass();
try {
// ②获取method对应的Method对象
Method methodObject = clazz.getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
// ③打开访问权限
methodObject.setAccessible(true);
// ④通过Method对象调用目标方法
methodObject.invoke(this, request, response);
} catch (Exception e) {
e.printStackTrace();
// 重要提醒:为了配合 TransactionFilter 实现事务控制,捕获的异常必须抛出。
throw new RuntimeException(e);
}
}
}
④继承关系
