【狂神说Java】SpringBoot最新教程IDEA版通俗易懂_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1PE411i7CV?p=14 学习之后的知识点总结:
1.自动装配回顾
我们可以通过自动配置类和yml文件绑定来进行修改默认值。
2.要解决的问题:
2.1 导入静态资源原理简介
2.1.1 找源码看看怎么配置静态资源。
在WebMvcAutoConfiguration这个自动配置类中,
有一个适配器Adapter。
里面有一个添加资源处理器的方法addResourceHandlers,代码如下:
"Default resource handling disabled"默认资源处理器已禁用。
前提条件,如果你在application.properties中引入了自定义的资源文件,那么以下默认资源处理器设置就失效了。
例如:
默认资源处理器设置失效。
那么,我们来分析后面的代码,发现有两种addResourceHandler方式引入web静态资源:
一种是:WebJars - Web Libraries in Jars https://www.webjars.org/
WebJars的方式,以Maven形式在pom文件中引入依赖,然后在 classpath:/META-INF/resources/webjars/ 这个目录下就可以找到,还能访问"/webjars/**"。
http://localhost:8080/webjars/jquery/3.2.1/jquery.js
另一种是:
点击“获取静态路径模式”getStaticPathPattern(),看到如下代码:
再次点击“静态路径模式staticPathPattern”,看到这个代码:
"/**"表示当前目录下的所有东西都能被识别。
然后,再看这段代码{ }里面的静态定位getStaticLocations():
点击“获取静态定位getStaticLocations()”,看到如下代码:
再次点击staticLocations,看到这个代码:
那么,分析这段代码,可以看到有四种路径可以得到静态资源:
"classpath:/META-INF/resources/", 是WebJars对应的目录"classpath:/META-INF/resources/webjars/”。 其余的都在resources中。 "classpath:/resources/", "classpath:/static/", "classpath:/public/" . “classpath:” 就是resources这个目录。
也就是说 ,"/**"下的所有资源都会去以上这四个目录中找。
我们来尝试一下,证明可以访问到内容:
再来验证一下看看哪一个优先级高:
说明优先级也是按照这个源码顺序来的。
分析源码得知有四种路径可以得到静态资源
"classpath:/META-INF/resources/",
"classpath:/resources/",(放一些upload,上传的文件)
"classpath:/static/",(放一些静态资源,例如图片等)
"classpath:/public/" .(可以放一些公共资源,例如大家都需要去访问的JS)
2.2 首页如何定制
FormattingConversionService(格式化转换服务) mvcConversionService,Provider(供应者) TemplateAvailabilityProviders(applicationContext)(模板可用性提供程序(应用内容))
setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
设置拦截器(获取拦截器(MVC转换服务,mvc资源url路径供应者))
setCorsConfigurations(getCorsConfigurations());
设置核心配置(获取核心配置)
getWelcomePage()方法点进去查看:
for循环在(String location : this.resourceProperties.getStaticLocations())也就是以下
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/" };
这几个文件里面寻找,获取首页地址location,如果找到就返回indexHtml;获取程序内容,如果程序内容不为空,调用方法getIndexHtml(Resource location)去寻找下的“/”里面的index.html,如果index.html存在,路径也存在,那么返回这个首页。不存在的话,就作为异常处理。
我们来尝试一下:
再次验证了资源处理优先级"classpath:/resources/">"classpath:/static/">"classpath:/public/" ,优先级最低的是"classpath:/public/"下的index.html。一个index.html也没有,就报异常了。另外,证明index.html直接放在"classpath:/"下,也就是放在"resources/"是不能被找到的,也会报异常。
2.2.2图标定制:页面的小图标如何修改?在任意资源目录下设置图片为 favicon.ico,就可以更改图标。然后发现360浏览器“清除上网痕迹之后”可以看到更改效果,谷歌浏览器要“清除上网痕迹之后”关掉浏览器重启,再重启服务器,才能看到。
然后我发现,我用的2.5.4版本,这个方式时灵时不灵,我暂时也不知道怎么改,如果你知道给我留个言,感谢感谢!
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
2.3 SpringBoot 不支持jsp,需要使用html配合模板引擎Thymeleaf
因为SpringBoot认为JSP过时了,所以不推荐使用jsp。而是使用HTML,然后配合模板引擎Thymeleaf。


Thymeleaf 官网:https://www.thymeleaf.org/
2.3.1导入依赖。2.3.0版本以后,改变导入方式,不使用以上方式。在2021年8月29日为止,最新版本的Spring Boot是2.5.4,直接导入spring-boot-starter-thymeleaf。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.5.4</version>
</dependency>
spring-boot-starter这个版本不再包含 spring-boot-starter-thymeleaf 了,都是单独的个体。
官网上关于模板引擎的解释:
Spring Boot Features
https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features
Spring Boot 特性
查看thymeleaf 百里香叶属性:
根据源码,
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
html页面需要放在templates目录下。
这时,我们尝试一下访问网页,根据以上代码,我们知道:模板引擎会自己加上前缀后缀来寻找页面。(我暂时是这样理解的,似乎不用再加上具体地址了。)
2.3.2查看thymeleaf,学习使用。
文档 - Thymeleaf https://www.thymeleaf.org/documentation.html
标题4是“标准表达式语法”。10是“属性优先级”。总之,多练习使用,才能熟练掌握。
我们尝试一下:
普通字符:
带转义字符的:
遍历:
model.addAttribute("users", Arrays.asList("幸","福","天","下"));
<h1 th:each="user:${users}" th:text="${user}"></h1>
遍历取值时,使用[[ ]]两个中括号也是可以的。
<h1 th:each="user:${users}" >[[${user}]]</h1>
2.4 装配扩展 Spring MVC
2.4.1 MVC配置原理
也没看明白。继续看看其他😂。大概就是:
如果您想保留那些 Spring Boot MVC 自定义并进行更多MVC 自定义(拦截器、格式化程序、视图控制器和其他功能),您可以添加自己的@Configuration并且是
WebMvcConfigurer类型的类,但不添加 @EnableWebMvc
.
我们尝试一下,添加自己的@Configuration
的类。
可以在我们自定义的类中重写这些方法。以前写MVC框架开发需要自定义的类,可以直接在@Configuration
的类中继承重写方法,更加方便快捷了!!!不需要一个一个的写类了。
Implement Methods Ctrl+I 实现(继承)方法,
Override Methods Ctrl+O 重写(覆盖)方法。
2.4.2 尝试 注册自定义的视图解析器
先分析ContentNegotiatingViewResolver(内容协商视图解析器)这个类(是根据客户提交的MimeType(如 text/html,application/xml)来跟服务端的一组viewResover的MimeType相比较,如果符合,即返回viewResover的数据。),
我们看到ContentNegotiatingViewResolver 类 继承了 WebApplicationObjectSupport(Web程序对象支持) ,WebApplicationObjectSupport实现了 ViewResolver视图解析器、Ordered命令、 InitializingBean 初始化Bean。
再分析ViewResolver视图解析器,
意思是:注意: 为了支持 viewResolver 链接,如果没有定义给定名称的视图,viewResolver 应该返回{@code null }。但是,这是不必要的:
一些视图解析器总是尝试用给定的名称构建视图对象,无法返回{@code null }(而是在视图创建失败时抛出异常)。
@param viewName 要解析的视图名称。
@param locale 要解析的视图场所。
支持国际化的视图解析器应该尊重这一点。
@return 视图对象,或者{@code null }如果没有找到(可选的,允许 viewResolver 链接)。
@throws Exception 如果视图不能被解析(通常在创建实际视图对象的情况下)。
我们可以发现ViewResolver 实现了视图解析器接口的类,我们就可以把它看作视图解析器。
我们来尝试一下怎样手动接管这个视图解析器!!尝试:
在ContentNegotiatingViewResolver(内容协商视图解析器)这个类里面
搜索resolveViewName解析视图名这个方法,发现代码描述的就是上面的注意事项。
那么,这个代码的内容有
获取候选的视图getCandidateViews,遍历寻找:
那么怎么从哪里get获取候选试图呢?从容器也就是Bean中获取候选视图,因为只有Bean里才能s使用get方法。所以我们想要自定义一个视图解析器,首先要
自定义一个视图解析器,然后把这个解析器加入Bean。
我看到这样一句话如下图,证明我们的自定义生效了。
在DispatcherServlet类中的doDispatch方法打个断点(因为所有的请求都会经过这个方法)验证。
/* 处理实际上分派给处理者。
处理程序将按servlet的HandlerMappings顺序来获得。
获取 HandlerAdapter 的方法是查询 servlet 安装的HandlerAdapters,以找到第一个支持该处理程序类的 HandlerAdapters。
所有的 http 方法都是通过这个方法处理的。决定哪些方法是可接受的,取决于HandlerAdapters或者handlers自己。
@param request ,当前 http 请求。
@param response, 当前 http 响应。
@throws Exception ,以防任何类型的处理失败。
*/
doDispatch方法打个断点之后,DeBug调试一下,然后访问http://localhost:8080/。
我们可以看到自定义的视图解析器:(还看到了前两个是官方的解析器,导入Thymeleaf之后的视图解析器,然后是我们自定义的解析器。)
🎉🎉🎉🎉🎉🎉🎉🎉😃😃😃😃😃😃😁😁😁😁✌
如果你想自定义一些功能,只要写出(@Configuration public class MyMvcConfig implements WebMvcConfigurer )组件,然后将它交给springboot,springboot就会帮我们自动装配。
2.4.3 尝试 配置 格式化转换器


图2代码分析:
图2的这句话表示,到 mvc配置文件中得到图3的Format格式,那么我们就可以在application.properties或者application.yml中配置。
Format format = this.mvcProperties.getFormat();
经过网络转换服务转换格式之后,添加到图1的addFormatters(conversionService)方法,经过格式器注册进Bean工厂。
在图3我们看到了这些格式,格式化程序获取的是DataTime 的格式`yyyy-MM-dd HH:mm:ss`

现在,我们已知“ 图2的这句话表示,到 mvc配置文件中得到图3的Format格式,那么我们就可以在application.properties或者application.yml中配置。”,那么怎么配置呢?点开mvcProperties。
发现找到最后根源还是图3。
那么我们在application.yml中尝试,看到如下图,可以设置三种时间格式。
那么使用这样的思路看看图1中的getMessageCodesResolverFormat(),点进这个方法之后看到

然后在application.yml中尝试:发现名称是一样的,时间也是这几个名称,只是中间加了小短线“-”,全部小写。这些也都是mvcProperties.调用方法找到的的WebMvcProperties.java中的类。
messageCodesResolverFormat。 date、time、dateTime 。
2.4.4 原理总结


要学会看源码,自己能出这个结论。
2.4.5 尝试 视图控制器
因为我们只控制了跳转,没有传数据,所以得到了一个空白页。
2.4.6 分析为什么 “加@Configuration并且是
WebMvcConfigurer类型的类”,但不添加 @EnableWebMvc?
我们发现@EnableWebMvc这个注解里面什么也没有,只是导入了一个
DelegatingWebMvcConfiguration.class类(Delegate 代表/委员/特派员)。
我们再次进入WebMvcAutoConfiguration.java类,找到WebMvcAutoConfigurationAdapter,里面也是导入了@Import(EnableWebMvcConfiguration.class)类,
进入这个类,我们看到它继承了DelegatingWebMvcConfiguration.class类。
在这个DelegatingWebMvcConfiguration.class类里我们可以看到:
DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport,
它里面的方法调用了WebMvcConfigurer里面的所有方法。就像下图所述,是一个WebMvcConfigurer的子集,授权自定义WebMvcConfigurationSupport。
那么我们知道,WebMvcAutoConfiguration.java这个类想要生效有以下条件:
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
“在找不到WebMvcConfigurationSupport.class类的时候,才能使WebMvcAutoConfiguration.java生效。”
而,DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport,
并且@EnableWebMvc这个注解里面什么也没有,只是导入了一个
DelegatingWebMvcConfiguration.class类(Delegate 代表/委员/特派员)。
所以两者条件冲突了。