SpringBoot基于Web的开发(一)

前言

了解怎么使用很简单,今天我们关注的重点在于SpringBoot底层是如何帮我们实现的。

1.我们先带着几个问题进行探究

Web这个场景SpringBoot帮我们配置了什么?我们能不能修改?能修改的话,可修改哪些配置?还有我们可不可以进行自身的扩展。

(1)先了解一下几个重要的概念: 在SpringBoot的源码中只要是

xxxAutoConfiguration: 帮我们给容器中自动配置组件
  xxxProperties: 配置类封装配置文件的内容

(2) 我们了解的是Web开发,那么SpringBoot底层为我们提供的自动配置类就是WebMvcAutoConfiguration。

在IDEA中按下Ctrl + N 可以进行相关类的搜索

非spring管理的bean怎么做切面_非spring管理的bean怎么做切面


这个类的源代码有500多行,哎头大,这谁顶得住呢。我们还是从一些简单方法入手,再逐步扩展。

(3) 我们先从SpringBoot对静态资源的隐射规则说起(也就是我们平时写的js,html.css等)

非spring管理的bean怎么做切面_静态资源_02


在这个类的473行中有一个addResourceHandlers( )方法,很明显是一个资源的处理方法。它的具体代码如下:

public void addResourceHandlers(ResourceHandlerRegistry registry) {
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
                CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
                if (!registry.hasMappingForPattern("/webjars/**")) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

                String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

            }
        }

从判断上我们可以看出就是在一个资源属性取东西,关键看 if (!registry.hasMappingForPattern("/webjars/**")) { 这个判断

this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));

3.2)这个句子也是一大堆看不懂的英文,但是我们要抓住重点addResourceHandler和addResourceLocations,这无非就是给我们改路径下的添加相应的资源处理器,还有资源加载路径。再看一该路径,我们就大概读懂了,就是当我们去访问地址为/webjars/**,都会去项目中 classpath:/META-INF/resources/webjars/ 找资源
3.3)那我们又有新疑问了,什么是webjars,它有什么用呢?
WebJars是将web前端资源(js,css等)打成jar包文件,然后借助Maven工具,以jar包形式对web前端资源进行统一依赖管理,保证这些Web资源版本唯一性。WebJars的jar包部署在Maven中央仓库上。
简单来讲webjars就是以jar包的方式引入静态资源。
3.4)那我们就从一个实例入手,真正了解一下这段源码的作用。
以jquery为例,只需在pom.xml文件中导入相应的依赖(这个依赖的详情可参考https://www.webjars.org/

<!--引入jquery-webjar-->
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.3.1</version>
</dependency>

这是我们打开项目的Maven依赖时会发现

非spring管理的bean怎么做切面_jar_03


此时我们在验证一下我们上面的猜想是否正确。

我们现在访问一下 localhost:8080/webjars/jquery/3.3.1/jquery.js (这就是上面所说的访问/webjars/这个路径,只需观察是否能找到相应的内容)

非spring管理的bean怎么做切面_Web_04


当页面呈现以上内容时,证明SpringBoot底层确实是这么映射的。
(4)上面的情况是针对特殊路径下的静态资源访问,那么其他没有特定路径下的静态资源该如何访问呢?
继续观察上面的代码(还是addResourceHandlers()方法下的484行)
按照我们日常编写代码的习惯,我们进行判断取值的时候,应该先排除一些特殊情况后,然后再编写普通情况(就像我们try-cath执行的时候),所以我们可以大胆猜测这就是我们所要找的 /
路径

String staticPathPattern = this.mvcProperties.getStaticPathPattern();

非spring管理的bean怎么做切面_jar_05


非spring管理的bean怎么做切面_Web_06


非spring管理的bean怎么做切面_jar_07


这也就证明了484行的这个判断确实是当我们访问根路径下时,静态资源的映射。

接着会到我们addResourceHandlers()方法下的这个判断

非spring管理的bean怎么做切面_非spring管理的bean怎么做切面_08


具体代码

关键看this.resourceProperties.getStaticLocations(),它还是包裹在addResourceLocations()里面,表明这是它的映射路径

this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));

非spring管理的bean怎么做切面_非spring管理的bean怎么做切面_09


非spring管理的bean怎么做切面_静态资源_10


这里我们就找的了它的隐射路径了,看代码中的21行

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

小结:当我们访问当前项目的任何资源(即/**)时,
(如:http://localhost:8080/项目的任何路径)
即我们输入 localhost:8080/abc ==>它会去静态资源文件里面找abc

那么它相关静态资源访问的路径为:
"classpath:/META-INF/resources/", 
"classpath:/resources/", 
"classpath:/static/", 
"classpath:/public/"
"/"

(5)欢迎页: 静态资源文件夹下的所有index.html页面,被”/**” 映射

比如我们访问 localhost:8080/ 找到的就是index.jsp页面

非spring管理的bean怎么做切面_Web_11


其中 第266行

WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());

5.1)this.getWelcomePage(),解释了找的页面是什么

非spring管理的bean怎么做切面_非spring管理的bean怎么做切面_12


5.2)this.mvcProperties.getStaticPathPattern()解释了我们映射的路径是什么(即我们访问什么路径的时候会显示index.jsp)

非spring管理的bean怎么做切面_jar_13


非spring管理的bean怎么做切面_静态资源_14


(6)我们图标的文件会在所有的 **/favicon.ico都是在静态资源文件下找(原理和上面一样)

小结:

通过上面的实例,我们发现我们很多Web的相关属性都是在ResourceProperties进行配置的,其实这不是偶然,这正是SpringBoot提供给我们WebMvc中参数的配置类(以后我们如果需要对Web中的相关参数进行更改是可以参考ResourceProperties类中的属性进行配置文件的更改)

非spring管理的bean怎么做切面_非spring管理的bean怎么做切面_15