123. 【深度解析SpringBoot源码B】
SpringBoot-核心功能
- (三)、SpringBoot核心功能
- 1.配置文件
- 1.1、properties
- 1.2、yaml
- (1).yaml 简介
- (2).yaml 基本语法
- (3).数据类型
- (4).示列
- 1.3、配置提示
- 2.WEB 开发
- 1.SpringMVC自动配置概览
- 2.简单功能分析
- (1).静态资源访问
- (1.1).静态资源目录
- (1.2).修改静态资源访问前缀
- (1.3).修改静态资源默认指定目录
- (1.4).支持webjars
- (2).欢迎页支持
- (3).静态资源配置原理 ⭐
- (1.1)、配置类只有一个有参构造器
- (1.2)、资源处理的默认规则
- (1.3)、静态页的欢迎规则
- 3.请求参数处理
- (1).请求映射
- (1.1)、rest使用与原理
- (1.2)、修改默认的_method更改为自定义的参数
- (1.3)、请求映射原理
- (2).普通参数与基本注解
- (1.1)、注解:
- (1.2)、Servlet API
- (1.5)、自定义对象参数
- (3).POJO封装过程
- (1.4)、复杂参数
- (4).参数处理原理
- (1.1)、HandlerAdapter
- (1.2)、执行目标方法
- (1.3)、参数解析器-`HandlerMethodArgumentResolver`
- (1.4)、返回值处理器
- (5).如何确定目标方法每一个参数的值
- (1.1)、挨个判断所有参数解析器那个支持解析这个参数
- (1.2)、解析这个参数的值
- (1.3)、自定义类型参数 封装POJO
- (6).目标方法执行完成
- (7).处理派发结果
(三)、SpringBoot核心功能
CTRL+H
打开的是 继承树
CTRL+F12
打开的是 方法结构
1.配置文件
1.1、properties
同以前的properties用法
1.2、yaml
(1).yaml 简介
YAML 是 “YAML Ain’t Markup Language”(YAML 不是一种标记语言
)的递归缩写。在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。
非常适合用来做以数据为中心的配置文件
(2).yaml 基本语法
- key: value;
kv之间有空格
大小写敏感
- 使用
缩进表示层级关系
-
缩进不允许使用tab
,只允许空格 - 缩进的空格数不重要,只要相同层级的元素
左对齐
即可 - '#'表示
注释
-
字符串无需加引号
,如果要加,''与""表示字符串内容 会被 转义/不转义 (单引号会转义特殊字符、双引号不会转义特殊字符。比如 \n ,单引号输出的是\n,双引号会换行)。 这里的转义是: 会不会修改原本的功能,转义就是把原有的功能给转义掉。
(3).数据类型
- 字面量:单个的、不可再分的值。date、boolean、string、number、null
k: v
- 对象:键值对的集合。map、hash、set、object
⭐行内写法的时候k1与 : 与 v1 都要有间隔,否则会默认讲k1:v1当作键
行内写法: k: {k1 : v1,k2 : v2,k3 : v3}
#或
k:
k1: v1
k2: v2
k3: v3
- 数组:一组按次序排列的值。array、list、queue
行内写法: k: [v1,v2,v3]
#或者
k:
- v1
- v2
- v3
假如一个文件中存在 application.yaml和application.properties那么两者都会生效的。
(4).示列
1.宠物类
package com.jsxs.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author Jsxs
* @Date 2023/7/2 9:06
* @PackageName:com.jsxs.bean
* @ClassName: Pet
* @Description: TODO
* @Version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Pet {
private String name;
private Double weight;
}
2.Person类: 匹配绑定并放入IOC容器中
package com.jsxs.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @Author Jsxs
* @Date 2023/7/2 9:05
* @PackageName:com.jsxs.bean
* @ClassName: Person
* @Description: TODO
* @Version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Component // 声明这是IOC容器中的一个组件
@ConfigurationProperties(prefix = "person") // 指定组件配置文件的前缀
public class Person {
private String userName;
private Boolean boss;
private Date birth;
private Integer age;
private Pet pet;
private String[] interests;
private List<String> animal;
private Map<String, Object> score;
private Set<Double> salarys;
private Map<String, List<Pet>> allPets;
}
3.application.yaml 配置文件
这里在行内写 k:v 的时候,一定要用空格间隔分来。 k 是橙色
person:
userName : jsxs
boss : true
birth : 2023/07/02 09:27:26
age : 18
pet :
name : 哈吉米
weight : 18.5
interests : [swiming,basck]
animal : [cat,dog]
score : {math : 131,english : 140}
salarys : [3999,4999.98,5999.99]
allPets :
jsxs : [{name : tom,weight : 15.3}]
4.测试
package com.jsxs.controller;
import com.jsxs.bean.Person;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
/**
* @Author Jsxs
* @Date 2023/7/2 9:37
* @PackageName:com.jsxs.controller
* @ClassName: IndexController
* @Description: TODO
* @Version 1.0
*/
@Controller
@ResponseBody
public class IndexController {
@Resource
Person person;
@GetMapping("/person")
public Person index(){
return person;
}
}
1.3、配置提示
自定义的类和配置文件绑定一般没有提示。
加入下面的依赖和配置之后,我们配置自定义的类时会有提示。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
2.WEB 开发
DispathServlet 和 SpringMvc
1. 先获得 url 请求的路径 ()
2. 获得 url 的那种解析器(5种)
3. 获得方法体参数的类型和个数
4. 遍历获得的参数 获得方法体参数的具体解析器 (27种)
5. 通过解析器开始解析方法体参数。
6. 再判断参数体中是否由注解,后面会给我们创建一个实列对象
7. 最后给我们创建的空实列对象进行赋值
SpringBoot官方 web开发文档
1.SpringMVC自动配置概览
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我们都无需自定义配置
)
The auto-configuration adds the following features on top of Spring’s defaults:
- Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
-
- 内容协商视图解析器和BeanName
视图解析器
- 内容协商视图解析器和BeanName
- Support for serving static resources, including support for WebJars (covered later in this document)).
-
-
静态资源
(包括webjars)
-
- Automatic registration of Converter, GenericConverter, and Formatter beans.
-
-
自动注册
Converter,GenericConverterFormatter
-
- Support for HttpMessageConverters (covered later in this document).
-
- 支持
HttpMessageConverters
(后来我们配合内容协商理解原理)
- 支持
- Automatic registration of MessageCodesResolver (covered later in this document).
-
- 自动注册 MessageCodesResolver (
国际化
用)
- 自动注册 MessageCodesResolver (
- Static index.html support.
-
- 静态i
ndex.html
页支持
- 静态i
- Custom Favicon support (covered later in this document).
-
自定义 Favicon
- Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
-
- 自动使用 ==ConfigurableWebBindingInitializer ==,(DataBinder负责将
请求数据绑定到JavaBean
上)
- 自动使用 ==ConfigurableWebBindingInitializer ==,(DataBinder负责将
If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.
不用@EnableWebMvc
注解。使用@Configuration + WebMvcConfigurer
自定义规则
If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.
声明WebMvcRegistrations 改变默认底层组件
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.
使用@EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管SpringMVC
2.简单功能分析
(1).静态资源访问
(1.1).静态资源目录
1.静态页面路径和静态资源不冲突
只要静态资源放在类路径classpath
下: called /static
(or /public
or /resources
or /META-INF
/resources
访问 : 当前项目根路径/ + 静态资源名
- 静态页面与静态资源冲突 (同名)
原理: 静态映射/**。 (即 localhost:8080/**)
网址请求进来,先去找Controller看能不能处理
。不能处理的所有请求又都交给静态资源处理器
。静态资源也找不到则响应404页面
控制层存在一个 /1.jpg的页面跳转,static下面存在着一张图片叫做 1.jpg
package com.jsxs.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Author Jsxs
* @Date 2023/7/2 10:54
* @PackageName:com.jsxs.controller
* @ClassName: HelloController
* @Description: TODO
* @Version 1.0
*/
@Controller
@ResponseBody
public class HelloController {
@GetMapping("/1.jpg")
public String hello(){
return "aaa";
}
}
1.静态资源默认访问的位置是 /** 即(localhost:8080/**)
spring:
mvc:
static-path-pattern: /**
(1.2).修改静态资源访问前缀
1.正常业务的开发中,我们需要对静态元加上前缀(主要目的是为了实现静态资源的拦截,这个前缀通常为控制层类的前缀)
spring:
mvc:
static-path-pattern: /res/**
http://localhost:8080/res/2.jpg
(1.3).修改静态资源默认指定目录
静态资源存放的默认路径有四个,实际开发中我们可能需要自定义指定我们的静态资源访问路径放哪里。
spring:
mvc:
static-path-pattern: /res/**
web:
resources:
# 这里的路径我们可以指定一个或多个,多个用[ ]括起来。
static-locations: classpath:/haha
查看static-locations的源码发现是一个数组
http://localhost:8080/res/2.jpg
把静态资源放在指定的目录下,才会被查找的到。
(1.4).支持webjars
通俗的讲就是讲 css js 等一些资源封装成了 Maven或者jar包
自动映射: webjars/**
webjars官网: https://www.webjars.org/
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.5.1</version>
</dependency>
访问地址:http://localhost:8080/webjars/jquery/3.5.1/jquery.js 后面地址要按照依赖里面的包路径
(2).欢迎页支持
Spring Boot supports both static and templated welcome pages. It first looks for an index.html file in the configured static content locations. If one is not found, it then looks for an index template. If either is found, it is automatically used as the welcome page of the application.
支持两种: 第一种(任意)静态资源目录目录下放index.html 第二种Controller下进行处理请求。
-
静态资源路径下 index.html
-
- 可以配置静态资源路径
-
- 但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问
spring:
# mvc:
# static-path-pattern: /res/**
web:
resources:
static-locations: classpath:/haha
-
controller能处理/index
(3).静态资源配置原理 ⭐
- SpringBoot启动默认加载
xxxAutoConfiguration
类(自动配置类) - SpringMVC功能的自动配置类
WebMvcAutoConfiguration
,生效
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {}
- 给容器中配了什么。
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}
- 配置文件的相关属性和xxx进行了绑定。
-
- WebMvcProperties==spring.mvc、
-
- ResourceProperties==spring.web.resources
(1.1)、配置类只有一个有参构造器
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnEnabledResourceChain
static class ResourceChainCustomizerConfiguration {
ResourceChainCustomizerConfiguration() {
}
@Bean
WebMvcAutoConfiguration.ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer(ResourceProperties resourceProperties, WebProperties webProperties) {
return new WebMvcAutoConfiguration.ResourceChainResourceHandlerRegistrationCustomizer((Resources)(resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources()));
}
}
@Configuration(
proxyBeanMethods = false
)
@EnableConfigurationProperties({WebProperties.class})
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
private final Resources resourceProperties;
private final WebMvcProperties mvcProperties;
private final WebProperties webProperties;
private final ListableBeanFactory beanFactory;
private final WebMvcRegistrations mvcRegistrations;
private final WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
private ResourceLoader resourceLoader;
//有参构造器所有参数的值都会从容器中确定 ⭐⭐⭐
//ResourceProperties resourceProperties;获取和spring.resources绑定的所有的值的对象
//WebMvcProperties mvcProperties 获取和spring.mvc绑定的所有的值的对象
//ListableBeanFactory beanFactory Spring的beanFactory ⭐ (容器)
//HttpMessageConverters 找到所有的HttpMessageConverters
//ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器。=========
//DispatcherServletPath
//ServletRegistrationBean 给应用注册Servlet、Filter....
public EnableWebMvcConfiguration(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, WebProperties webProperties, ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ListableBeanFactory beanFactory) {
this.resourceProperties = (Resources)(resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources());
this.mvcProperties = mvcProperties;
this.webProperties = webProperties;
this.mvcRegistrations = (WebMvcRegistrations)mvcRegistrationsProvider.getIfUnique();
this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
this.beanFactory = beanFactory;
}
(1.2)、资源处理的默认规则
因为这里分析得到: 假如resourceProperties.isAddMappings()为false下面的业务逻辑都不生效,也就是说默认配置的路径都不会生效。 @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 静态资源是否全部生效 ⭐ if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); return; } Duration cachePeriod = this.resourceProperties.getCache().getPeriod(); CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl(); //webjars的规则 if (!registry.hasMappingForPattern("/webjars/**")) { customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/") .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl)); } // String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern) ⭐ .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())) .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl)); } }
上一篇: 深入探讨批处理bat中的复制命令Copy与Xcopy
下一篇: 我开发了一个令人惊叹的功能!
推荐阅读
123. 【深入解析SpringBoot源码B】(第四部分)
123. 【深度解析SpringBoot源码B】
深入解析SpringBoot全局配置文件加载原理(涵盖详细源码分析)
解析Spring5.0源码下Configuration注解的深度理解
深度剖析Linux内核源码(32):DPDK核心源码解析(二)
Android Dpdk源码解析:深度理解dp代码
Vue中遇到新旧值相同的watch问题,该如何解决?——深度探究源码解析
深度解析Spring源码:如何处理循环依赖问题?(易懂且优秀)
鸿蒙v78.01内核源码详解:消息映射深度解析 - LiteIpc进程通信机制第二部分 | 一系列百篇博文中揭秘OpenHarmony源代码探索
springboot封装请求参数json的源码解析