SpringBoot-Web开发之视图解析
- SpringBoot默认不支持jsp模板,故需引入第三方模板引擎实现页面渲染
- springboot默认打包方式是jar包,jsp不支持在压缩包内编译
- 常见结合使用的视图:Freemarker、Thymeleaf、Vue
视图解析流程
- 举例一个redirect流程
@PostMapping("/login")
public String main(User user, HttpSession session, Model model){if (!StringUtils.isEmpty(user.getUserName()) && "123456".equals(user.getPassword())) {session.setAttribute("loginUser", user);// 重定向,防止表单重复提交return "redirect:/main.html";}else {model.addAttribute("msg", "账号密码错误");return "login";}}@GetMapping("/main.html")
public String mainPage(HttpSession session,Model model){Object user = session.getAttribute("loginUser");if (user == null) {model.addAttribute("msg", "请重新登录");return "login";}else {return "main";}
}
- 目标方法处理的过程中,所有数据都会被放在 ModelAndViewContainer 里面。包括请求传入数据和视图地址
- controller方法的传入参数是一个自定义类型对象(从请求参数中确定的),通过ModelAttributeMethodProcessor类的resolveArgument()塞入传入的参数
- 通过ViewNameMethodReturnValueHandler类的handleReturnValue()塞入视图数据


- 任何目标方法执行完成以后都会返回 ModelAndView(数据和视图地址)

- processDispatchResult 处理派发结果(页面该如何响应)

render()进行页面渲染逻辑
- 根据方法的String返回值得到 View 对象,所有的视图解析器尝试是否能根据当前返回值得到View对象

- ContentNegotiationViewResolver 里面包含了其余所有的视图解析器,内部还是利用其他视图解析器得到视图对象
- 此时redirect:/main.html --> ThymeleafViewResolver类new RedirectView()


- 视图对象view.render(mv.getModelInternal(), request, response); 视图对象调用自定义的render进行页面渲染工作
- RedirectView获取目标url地址
- 调用原生servlet方法response.sendRedirect(encodedURL)重定向




视图解析类型
- 返回值以 forward: 开始
- new InternalResourceView(forwardUrl)
- 转发request.getRequestDispatcher(path).forward(request, response)
- 返回值以 redirect: 开始
- new RedirectView()
- render()渲染,此时就是重定向
- 返回值是普通字符串
- new ThymeleafView()
- render()渲染,调用模板引擎的process方法进行页面渲染(用writer输出)
Thymeleaf
1. Thymeleaf简介
- 现代化,服务器端Java模板引擎,适用于Web和独立环境
- 由于各种绑定与控制采用属性的方式,可以使得模板不破坏html原有的语法结构
- 仍然以controller来控制路由,而不是nodejs(例如使用vue)
- 官网地址:https://www.thymeleaf.org
2. 基本语法
- 官方文档地址: 官方文档
- 表达式
| 表达式名字 | 语法 | 用途 |
| 变量取值 | ${...} | 获取请求域、session域、对象等值 |
| 选择变量 | *{...} | 获取上下文对象值 |
| 消息 | #{...} | 获取国际化等值 |
| 链接 | @{...} | 生成链接 |
| 片段表达式 | ~{...} | jsp:include 作用,引入公共页面片段 |
3. 基本使用
- 引入依赖
- 所有thymeleaf的配置值都在 ThymeleafProperties
- 配置好了 SpringTemplateEngine、ThymeleafViewResolver
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 开发页面
- html放在如图路径
- 引入名称空间:<html xmlns:th="http://www.thymeleaf.org">

4. 请求路径自动添加上下文路径:例如请求路径hello ,上下文路径是/SpringMVC
- @{/hello} = /SpringMVC/hello
- @{hello} = /hello
5. RESTFul地址拼接,例如拼接请求地址+查询参数id
- 方式一:@{'/请求地址/'+${id}}
- 方式二:@{/请求地址/}+${id}
6. 行内写法:[[${ key }]]
- 参考:官方文档
- 例如:<p>Hello, [[${session.user.name}]]!</p>
7. 获取域对象数据
- ${key}
- ${session.key}
- ${application.key}
8. 引入公共页面:官方参考
- 被引入页面b的定义
- th:fragment="模块名"
- id="模块名"
- 引入a页面,使用fragment
- th:insert="b名称 :: 模块名":将模块引入到当前标签下
- th:replace="b名称 :: 模块名":将模块与当前标签下内容作替换
- th:include="b名称 :: 模块名":将模块内容引入到当前标签下
- 如果使用id引入,需要在模块名前加上#
8. 循环:官方参考
- 语法一:th:each="item : ${items}" 简单循环
- 语法二:th:each="item,itemStatu : ${items}" statu可以获取当前循环状态,例如索引号
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'"><td th:text="${prod.name}">Onions</td><td th:text="${prod.price}">2.41</td><td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>