4. springboot----- SpringMVC + webjars + Thymeleaf + 热部署




1. springboot中的SpringMVC

1. Springboot的默认配置
  • Web 开发是项目实战中至关重要的一部分,Web开发的核心内容主要包括嵌入的 Servlet 容器和SpringMVC

  • Web开发官方文档:https://docs.spring.io/spring-boot/docs/2.0.6.RELEASE/reference/htmlsingle/#boot-features-spring-mvc

  • Spring Boot 为 Web 开发提供了 spring-boot-starter-web 启动器作为基本支持,为我们提供了嵌入的Tomcat 以及 Spring MVC 的依赖支持。(参考:pom.xml)(详情我们可以分析 spring-boot-starter-web

  • 也提供了很多不同场景的自动配置类,让我们只需要在配置文件中指定少量的配置即可启动项目。自动配置
    类存储在 spring-boot-autoconfigure.jar 的 org.springframework.boot.autoconfigure 包下。
    在这里插入图片描述

2. 自动配置类举例(还有很多):
  1. 文件名可以看出
    xxxxAutoConfiguration :向容器中添加自动配置组件
    xxxxProperties :使用自动配置类 来封装 配置文件的内容

  1. SpringMVC的配置 : WebMvcAutoConfiguration 和 WebMvcProperties
    在这里插入图片描述

  2. 内嵌 Servlet 容器 : ServletWebServerFactoryAutoConfiguration 和 ServerProperties
    在这里插入图片描述



3.分析 SpringMVC 自动配置(接下来4步暂时没用到,所以暂时放一边)
  1. 如果想保留 Spring Boot MVC的特性,而且还想扩展新的功能(拦截器, 格式化器, 视图控制器等),你可以在你自定义的 WebMvcConfigurer 类上增加 @Configuration 注解。

  2. 如果你想全面控制SpringMVC(也就是不使用默认配置功能), 你在自定义的Web配置类上添加@Configuration 和 @EnableWebMvc 注解。



4. 扩展 SpringMVC 功能



5. 全面控制 SpringMVC



6. 总结 SpringMVC 配置
  1. 在Spring Boot中自已配置组件的时候,先看容器中有没有公司自已配置的(@Bean、@Component),如果有就用公司自已配置的; 如果没有,才自动配置.
  2. 在Spring Boot中会有非常多的xxxConfigurer帮助我们进行扩展配置.
  3. 在Spring Boot中会有很多的xxxCustomizer帮助我们进行定制配置.





2. 静态资源的映射规则

先总结:可通过访问其他目录获取静态资源文件,并不是表面写的文件夹一层一层去获取,详细可看下方
对静态资源的映射规则, 可通过分析 WebMvcAutoConfiguration 自动配置类得到 springboot

1. webjars 资源映射
  1. 什么是 webjars ?
    WebJars是将客户端(浏览器)资源(JavaScript,Css等)打成jar包文件,以对资源进行统一依赖管理。WebJars的jar包部署在Maven中央仓库上。
    具体可看: https://blog.csdn.net/weixin_41888813/article/details/81061676



2. 分析
  1. 所有 /webjars/** 请求,都去 classpath:/META-INF/resources/webjars/ 目录找对应资源文件
    在这里插入图片描述

  2. webjars:以jar包的方式引入静态资源

  3. 在官网打开资源文件的依赖配置信息,然后粘贴到 pom.xml 中

<!--引入 jquery webjars(引入了jq的依赖)->
<dependency>
	<groupId>org.webjars</groupId>
	<artifactId>jquery</artifactId>
	<version>3.3.1</version>
</dependency>
  1. 访问 localhost:8080/webjars/jquery/3.3.1/jquery.js 会在下面路径 中查找‘’
    在这里插入图片描述

在这里插入图片描述



3. 其他静态资源映射

在 WebMvcAuotConfiguration.addResourceHandlers() 分析 访问其他资源映射
总结:当接受到 /** 请求访问资源时, 会被映射到下面4个 类路径下的静态资源目录中 查找

classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/

访问 localhost:8080/style.css 会在上面四个静态资源路径 中查找文件,如下所示:
在这里插入图片描述
在这里插入图片描述



4. 欢迎页映射

在 WebMvcAuotConfiguration.welcomePageHandlerMapping() 分析 欢迎页映射
总结:分析后, 会从 4个静态资源目录 + 根路径 / 中 查找 index.html 页面

classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
/: 当前项目根路径下

会在 静态资源目录下 与 根路径查找 (按该顺序) index.html页面; 收到 "/* * " 请求映射
访问 localhost:8080/ 会在上面5个目录中查找 index.html 页面(因为/也属于 /** )
在这里插入图片描述
在这里插入图片描述



5. 图标映射

Spring Boot 会在静态资源目录下 与 根路径(按该顺序) 查找 faicon.ico 页面;
如果存在这样的文件,Spring Boot 会自动将其设置为应用图标。

classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
/: 当前项目根路径下




3. Thymeleaf 模板引擎(与品优购学的Freemarker是一种东西)

Spring Boot 官方不推荐使用JSP,因为内嵌的 Tomcat 、Jetty 容器不支持以 jar 形式运行 JSP。Spring Boot
中提供了大量模板引擎,包含 Freemarker、Mastache、Thymeleaf 等。 而 Spring Boo官方推荐使用Thymeleaf 作为模板引擎, 因为 Thymeleaf 提供了完美的 SpringMVC 的支持。

1. 引入 Thymeleaf
  1. pom.xml 加入 Thymeleaf 启动器
<!-- thymeleaf 模板启动器 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>



2. 使用 Thymeleaf
  1. 模板文件放在哪里 ?

在这里插入图片描述
          通过上面分析发现, 将 HTML 页面 放到 classpath:/templates/ 目录下, Thymeleaf 就能自动渲染

@RequestMapping("/execute")
public String execute(Map<String, Object> map) {
map.put("name", "梦学谷");
// classpath:/templates/success.html
return "success";
}

          发送 http://localhost:8080/execute 后, 通过上面代码转到 classpath:/templates/success.html


  1. 导入 Thymeleaf 的名称空间
    在 html 页面加上以下名称空间, 使用 Thymeleaf 时就有语法提示。
<html xmlns:th="http://www.thymeleaf.org">

          演示 Thymeleaf 语法

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<h2 >成功</h2>
<!--th:text 设置p标签的标签体内容-->
<p th:text="${name}">这里显示名字</p>
</body>
</html>



3. Thymeleaf 语法
  1. 声明与引入公共片段
<!--header.html-->
<body>
	<!--声明公共片段-->
	<!-- 方式1-->
	<div th:fragment="header_common">
		这是th:fragment声明公共片段
	</div>
	<!-- 方式2:选择器写法-->
	<div id="header_common_id">
		这是id选择器声明公共片段
	</div>
</body>



<!-- success.html 引入头部公共片段 -->
<!--方式1:
header : 公共片段所在模板的文件名
header_common :声明代码片段名 -->

<div th:replace="header :: header_common"></div>



<!--方式2:选择器写法
header : 公共片段所在模板的文件名
#header_common_id: 声明代码片的id值
-->

<div th:replace="header :: #header_common_id"></div>

<!--
th:insert 和 th:replace的区别
th:insert和th:replace都可以引入片段,两者的区别在于
th:insert: 保留引入时使用的标签
th:replace:不保留引入时使用的标签, 将声明片段直接覆盖当前引用标签
-->

<h2 th:insert="header :: #header_common_id"></h2>

  1. 迭代 th:each
    HelloController

@RequestMapping("/study")
public String study(Map<String, Object> map, HttpServletRequest request) {
	List<User> userList = new ArrayList<>();
	userList.add(new User("小梦", 1));
	userList.add(new User("小李", 2));
	userList.add(new User("小张", 1));
	map.put("userList", userList);
	return "study";
}

study.html

<table border="1px">
	<tr>
		<th>姓名</th>
	</tr>
	<!--方式1-->
	<tr th:each="user : ${userList}">
		<!--每次迭代都会生成一个当前标签-->
		<td th:text="${user}">mengxuegu</td>
	</tr>
</table>
<hr/>
<ul>
	<!--方式2-->
	<!--作用在同一个标签上, 每次迭代生成一个当前标签-->
	<li th:each="user : ${userList}" th:text="${user}"></li>
</ul>

获取迭代状态

<table border="1px">
	<tr>
		<th>编号</th>
		<th>姓名</th>
		<th>总数</th>
		<th>偶数/奇数</th>
		<th>第一个元素</th>
		<th>最后一个元素</th>
	</tr>
	<!--
	user :1个值,代表每次迭代出对象,名字任意取
	iterStat :2个值,代表每次迭代器内置对象, 名字任意取, 并有如下属性:
	index : 当前迭代下标 0 开始
	count : 当前迭代下标 1 开始
	size : 获取总记录数
	current : 当前迭代出的对象
	even/odd : 当前迭代是偶数还是奇数 (1开始算,返回布尔值)
	first : 当前是否为第一个元素
	last : 当前是否为最后一个元素
	-->
	<tr th:each="user, iterStat : ${userList}">
		<td th:text="${iterStat.count}">0</td>
		<td th:text="${user.username}">mengxuegu</td>
		<td th:text="${user.gender == 1 ? '女' : '男'}">未知</td>
		<td th:text="${iterStat.size}">0</td>
		<td th:text="${iterStat.even}? '偶数' : '奇数'"></td>
		<td th:text="${iterStat.first}"></td>
		<td th:text="${iterStat.last}"></td>
	</tr>
</table>

  1. 条件判断
    th:if 不仅判断返回为 true 的表达式,还判断一些特殊的表达式。
    th:unless 与 th:if 作用正好相反。

在这里插入图片描述

<hr/>
下面加not
<h3 th:if="not ${#lists.isEmpty(userList)}">th:if判断,如果此文字显示说明有值</h3>
<h3 th:unless="${#lists.isEmpty(userList)}">th:unless判断,如果此文字显示说明有值</h3>

th:swith th:case

@RequestMapping("/study")
public String study(Map<String, Object> map, HttpServletRequest request) {
	List<User> userList = new ArrayList<>();
	userList.add(new User("小梦", 1));
	userList.add(new User("小李", 2));
	userList.add(new User("小张", 1));
	map.put("userList", userList);
	// 1女, 2男
	map.put("sex", 1);
	map.put("man", 2);
	return "study";
}
------------------------------
<div th:switch="${sex}">
<!--1, 2-->
	<p th:case="1"></p>
	<!--判断sex的值和下面取出man的值是否相等,相等则显示-->
	<p th:case="${man}"></p>
	<!--如果值都不在上述case里,则th:case="*"语句生效。-->
	<p th:case="*">未知</p>
</div>



  1. 显示标签体内容
    th:text 转义特殊字符, 即 h1标签以文本显示出来
    th:utext 不转义特殊字符, 即 h1 标签展现出本来效果
@RequestMapping("/study")
public String study(Map<String, Object> map, HttpServletRequest request) {
	List<User> userList = new ArrayList<>();
	userList.add(new User("小梦", 1));
	userList.add(new User("小李", 2));
	userList.add(new User("小张", 1));
	map.put("userList", userList);
	// 1女, 2男
	map.put("sex", 1);
	map.put("man", 2);
	// th:text th:utext
	map.put("desc", "欢迎来到<h1>梦学谷<h1>");
	return "study";
}


<hr/>
<div th:text="${desc}"> </div>
<div th:utext="${desc}"> </div>

      补充:Thymeleaf 行内表达式双中括号: [[表达式]] (就是不在标签上使用属性,参考12 Inlining)

<input type="checkbox" /> [[${desc}]]
<p>Hello, [[${desc}]] 。。。</p>



  1. th:object 直接取出对象
    使用th:object 直接取出对象,然后写对象里的属性名即可获取属性值
@RequestMapping("/study")
public String study(Map<String, Object> map, HttpServletRequest request) {
	List<User> userList = new ArrayList<>();
	userList.add(new User("小梦", 1));
	userList.add(new User("小李", 2));
	userList.add(new User("小张", 1));
	map.put("userList", userList);
	// 1女, 2男
	map.put("sex", 1);
	map.put("man", 2);
	// th:text th:utext
	map.put("desc", "欢迎来到<h1>梦学谷<h1>");
	request.getSession().setAttribute("user", new User("小不点", 2));
	return "study";
}

----------------------------------



<!--使用th:object 直接取出对象,然后写对象里的属性名即可获取属性值-->
<div th:object="${session.user}">
	<p>
	姓名:<span th:text="*{username}">xxxx</span>
	</p>
	<p>
	性别:<span th:text="*{gender == 1 ? '女' : '男'}">xxxx</span>
	</p>
</div>




4. SpringBoot 热部署

1. 什么是热部署?
  • 默认情况下, 在开发中我们修改一个项目文件后,想看到效果不得不重启应用,这会导致浪费大量时间 ,我们希望不重启应用的情况下,程序可以自动部署(热部署)。



2 .如何能实现热部署?
  1. 关于模板引擎:在 Spring Boot 开发环境下禁用模板缓存
#开发环境下关闭thymeleaf模板缓存,thymeleaf默认是开启状态
spring.thymeleaf.cache=false

  1. 添加 Spring Boot Devtools 热部署依赖
<!--热部署-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-devtools</artifactId>
</dependency>

  1. Intellij IEDA和Eclipse不同,Intellij IDEA必须做一些小调整:
          在Intellij IEDA 中,修改文件后都是自动保存,默认不会自动编译文件,需要手动编译按 Ctrl + F9 (推荐使用)或 Build -> Build Project ;

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值