springboot2

springboot2

配置文件

  1. 见到很多 spring-boot-starter-* ; * 就表示某种场景

  2. 只要引入 starter ,这个场景的所有常规需要的依赖都会自动注入

1
2
3
4
5
6
  <!-- 所有场景最底层的依赖 --> 
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
  • 自动配置 tomcat
  • mvc
  • web常见的功能
  • 默认的包结构
  • 各种配置拥有默认值
    • 默认配置最终都是映射到 MultipartProperties
    • 配置文件的值最终会绑定到每个类上,这个类会在容器中创建对象
  • 按需加载所有配置项

web 开发

1、容器功能

1.1、组件添加

  1. @Configuration
    • 基本使用 类上添加 @Configuration 表示该类为配置类,方法上加上 @Bean 将返回对象注入容器,方法名为 Bean 的名字
    • Full 模式 和 Lite 模式
      • 配置类组件之间无依赖关系用 lite 模式加速容器启动过程,减少判断
      • 配置类组件之间有依赖关系,方法会被调用得到之前的单实例组件,用 Full 模式
    • @Import({Class.class}) 在容器中创建出这个类型的组件,默认组件的名字是全类名
    • @Condition 条件装配:满足 Conditional 指定的条件,则进行组件注入

2、原生配置文件引入

  1. @ImportResource(“”) 导入 spring 配置文件

3、配置绑定

  1. @ConfigurationProperties(prefix=””),prefix 中值要小写
  2. 配置类上添加 @EnableConfigurationProperties

4、自动配置管理

  • @SpringBootConfiguration,代表当前是一个配置类

  • @ComponentScan,指定扫描哪些 spring 注解

  • @EnableAutoConfiguration

    • ```java
      @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @AutoConfigurationPackage
      @Import({AutoConfigurationImportSelector.class})
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10

      - `@AutoConfigurationPackage` 指定了默认的包规则

      ```java
      @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @Import({Registrar.class}) // 给容器中导入组件
      // 利用 Registrar 给 spring 容器注册一系列组件
  • @Import(AutoConfigurationImportSelector.class)

    1
    2
    3
    4
    5
    6
    7
    1、 利用 getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) 给容器中批量导入一些组件
    2、 调用 List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) 获取所有需要导入到容器中的组件
    3、 利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) 得到所有的组件
    4、 从 META-INF/spring.factories 位置来加载一个文件
    默认扫描当前系统里面所有 META-INF/spring.factories 位置的文件
    spring-boot-autoconfigure-2.3.2.RELEASE.jar 包里面也有 META-INF/spring.factories
    文件里面写死了 springboot 一启动就要给容器中加载的所有配置类

5、按需开启配置项

按照条件装配规则,按需装配

  • springboot 先加载所有的自动配置类 xxxAutoConfiguration
  • 每个自动配置类按条件生效,默认都会绑定配置文件指定的值,从 xxxProperties 里面拿,而 xxxProperties 和配置文件进行了绑定
  • 生效的配置类就会给容器中装配很多组件
  • 只要容器中有这些组件,相当于启用了这些功能
  • 定制化配置
    1. 直接用 @Bean 替换底层的组件
    2. 修改配置文件
  • 自定义器 xxxCustomizer

xxxAutoConfiguration -> 组件 -> xxxProperties 获取值 -> application.properties

6、简单功能分析

6.1、静态资源访问

6.1.1、静态资源目录

类路径下:/static(or /public or /resources or /META-INF/resources)

访问:当前项目根路径/ + 静态资源名

原理:静态映射/**

请求进来,先去找 controller 看能不能处理,不能处理的所有请求又都交给静态资源处理器。静态资源处理也没找到就是 404

6.1.2、访问前缀

1
2
3
4
5
6
# 方便拦截器拦截
spring:
mvc:
static-path-pattern: /res/**
resources: #指定静态资源目录
static-location: [classpath:/index]

6.2、请求参数处理

6.2.1、请求映射

@xxxMapping

RequestMappingHandlerMapping:保存了所有 @RequestMapping 和 handler 的映射规则

可以自定义 HandlerMapping 放入容器中

6.2.2、普通参数与基本注解

  1. 注解:

    @PathVariable、@RequestHeader、@RequestAttribute、@ModelAttribute(矩阵变量 )、@RequestParam、@MatrixVariable、@CookieValue、@RequestBody

  2. Servlet API:

    WebRequest、ServletRequest、MultipartRequest、HttpSession、javax.servlet.http.PushBuilder、Principal、InputStream、Reader、HttpMethod、Locale、TimeZone、ZoneId

  3. 复杂参数

    Map、Errors/BindingResult、Model(map、model 里面的数据会被放在 request 的请求域中即: request.setAttribute()

    )、RedirectAttributes(重定向携带参数)、ServletResponse(response)、SessionStatus、UriComponentBuilder、ServletUriComponentsBuilder

  4. 自定义对象参数

    可以自动类型转换与格式化,可以级联封装

处理过程(DispatcherServlet):

  • HandlerMapping 中找到能处理请求的 Handler(Controller.method)
  • 为当前 Handler 找一个适配器 HandlerAdapter
  • 参数解析器,InvocableHandlerMethod
  • 返回值解析器

6.3、内容协商

根据客户端接收能力不同,返回不同媒体类型的数据(调整请求头中 Accept 属性)。

  1. 判断当前响应头中是否已经有确定的媒体类型,MediaType
  2. 获取客户端(postman、浏览器)支持接受的内容类型。(获取客户端 Accept 请求头字段)
    • ContentNegotiationManager 内容协商管理器,默认使用基于请求头的策略
    • HeaderContentNegotiationStrategy 确定客户端可以接收的内容类型
  3. 遍历循环所有支持当前系统的 MessageConverter,看谁支持操作这个对象
  4. 找到支持操作这个对象的 converter,把 converter 支持的媒体类型统计出来
  5. 进行内容协商的最佳匹配媒体类型
  6. 用支持将对象转为最佳匹配媒体的类型的 converter,调用它进行转化

开启浏览器参数方式内容协商功能

  • 为了方便内容协商,开启基于请求参数的内容协商功能(spring.favor-parameter=true)
  • (参数添加 format=json/xml)

自定义 MessageConverter,WebMavConfigurer 类中重写 extendMessageConverters 方法

有可能添加的自定义功能会覆盖默认的很多功能,导致一些默认功能失效

6.4、拦截器

新建类实现 HandlerInterceptor 接口,再新建类实现 WebMvcConfigurer 接口,在 addInterceptors 方法中将拦截器添加到容器中,并配置拦截哪些路径和放行哪些路径。

流程

  1. 根据当前请求,找到 HandlerExecutionChain(可以处理请求的 handler 以及 handler 的所有拦截器)
  2. 先来顺序执行所有拦截器的 preHandle 方法
    • 如果当前拦截器 preHandle 返回为 true,则执行下一个拦截器的 preHandle
    • 如果当前拦截器返回为 false,则去倒序执行所有已经执行了的拦截器的 afterCompletion
  3. 如果任何一个拦截器返回 false,直接跳出不执行目标方法
  4. 所有拦截器都返回 true,执行目标方法
  5. 倒序执行所有拦截器的 postHandle 方法
  6. 前面步骤有任何异常都会直接执行 afterCompletion
  7. 页面成功渲染之后,也会倒序触发 afterCompletion

6.5、文件上传

文件上传自动配置类:MultipartAutoConfiguration - MultipartProperties

  • 自动配置好了 StandardServletMultipartResolver(文件上传解析器)
  • 原理:
    1. 请求进来使用文件上传解析器判断(isMultipart)并封装(resolveMultipart,返回 MultipartHttpServeletRequest)文件上传请求
    2. 参数解析器来解析请求中的文件内容封装成 MultipartFile
    3. 将请求头中的文件信息封装为一个map MultiValueMap<String,MultipartFile>

6.6、异常处理

6.6.1、错误处理

  • 默认情况下,Springboot 提供 /error 处理所有错误的映射
  • 对于机器客户端,它将生成 JSON 响应,其中包含错误,Http 状态和异常消息的详细信息,对于浏览器客户端,响应一个错误视图,以 HTML 格式呈现相同的数据
  • 要对其进行自定义,添加 View 解析为 error
  • 要完全替换默认行为,可以实现 ErrorController 并注册该类型的 Bean 定义,或添加 ErrorAttributes 类型的组件以使用现有机制但替换其内容
  • error/ 下的 4xx,5xx 页面会被自动解析

6.6.2、定制错误处理逻辑

  • 自定义错误页
    • error/404.html error/5xx.html
  • @ControllerAdvice + @ExceptionHandler 处理异常
  • ErrorViewResolver 实现自定义处理异常
  • 实现 HandlerExceptionResolver 处理异常

6.7、web 原生组件注入

集成 servlet、filter、listener

  • 主类添加 @ServletComponentScan 注解扫描包
  • 新建类添加 @WebServlet 注解

6.8、嵌入式 servlet 容器

  1. 切换嵌入式 Servlet 容器
    • 默认支持的 webServer
      • tomcat,jetty,undertow
      • ServletWebServerApplicationContext 容器启动寻找 ServletWebServerFactory 并引导创建服务器
    • 切换服务器
  2. 定制 servlet 容器
    • 实现 WebServerFactoryCustomizer
    • 修改配置文件 server.xxx
    • 直接定义 ConfigurableServletWebServerFactory

JUnit5 单元测试

JUnit5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

  • JUnit Platform:是在 JVM 上启动测试框架的基础,不仅支持 Junit 自制的测试引擎,其它测试引擎也都可以接入
  • JUnit Jupiter:提供了 JUnit5 的心的编程模型,是 JUnit5 新特性的核心,内部包含一个测试引擎,用于在 Junit Platform 上运行
  • JUnit Vintage:提供了兼容 JUnit4.x Junit 3.x 的测试引擎

7、常用注解

  • @Test:表示方法是测试方法,它的职责非常单一,不能声明任何属性,拓展的测试将会由 Jupiter 提供额外的测试
  • @ParameterizedTest:表示方法是参数化测试
  • @RepeatedTest:表示方法可重复执行
  • @DisplayName:为测试类或者测试方法设置展示名称
  • @BeforeEach:表示在每个单元测试之前执行
  • @AfterEach:表示在每个单元测试之后执行
  • @BeforeAll:表示在所有单元测试之前执行
  • @AfterAll:表示在所有单元测试之后执行
  • @Tag:表示单元测试类别
  • @Disabled:表示测试类或测试方法不执行
  • @Timeout:表示测试方法运行如果超过了指定时间将会返回错误
  • @ExtendWith:为测试类或测试方法提供扩展类引用

8、单元测试

断言(assertions)是测试方法中的核心部分,用来对测试需要满足的条件进行验证。

  • 检查业务逻辑返回的数据是否合理
  • 所有的测试运行结束以后,会有一个详细的测试报告
方法 说明
assertEquals 判断两个对象或两个原始类型是否相等
assertNotEquals 判断两个对象或两个原始类型是否不相等
assertSame 判断两个对象引用是否指向同一个对象
assertNotSame 判断两个对象引用是否指向不同对象
assertTrue 判断给定的布尔值是否为 true
assertFalse 判断给定的布尔值是否为 false
assertNull 判断给定的对象引用是否为 null
assertNotNull 判断给定的对象引用是否不为 null

9、前置条件

前置条件(assumptions【假设】)类似于断言,不同之处在于不满足的断言会使得测试方法失效,而不满足前置条件只会使得测试方法的执行终止,前置条件可以看成是测试方法执行的前提,当该前提不满足时,就没有继续执行的必要了。

10、参数化测试

不同的参数多次进行单元测试,可以使用不同的参数进行多次单元测试,而不需要每新增一个参数就要新增一个单元测试

@ValueSource:为参数化测试指定入参来源,支持八大基础类型以及 String 类型,Class 类型

@NullSource:表示为参数化测试提供一个 null 的入参

@EnumSource:表示为参数化测试提供一个枚举入参

@CsvFileSource:表示读取指定 CSV 文件内容作为参数化测试入参

@MethodSource:表示读取指定方法的返回值作为参数化测试入参

生产指标监控

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
1
2
3
4
5
6
management:
endpoints:
enabled-by-default: true #暴露所有端点信息
web:
exposure:
include: '*' # 以 web f

stater 启动原理

  • stater - pom 引入 autoconfigure 包

    1
    2
    3
    4
    5
    6
    graph LR

    A(starter) -->B(autoconfigure)

    B --> C(spring-boot-starter)

  • autoconfigure 包中配置使用 META-INF/spring.factories 中 EnableAutoConfiguration 的值,使得项目启动加载指定的自动配置类

  • 编写自动配置类 xxxAutoConfiguration -> xxxProperties

    • @Configuration
    • @Conditional
    • @EnableConfigurationProperties
    • @Bean
    • ………

引入 starter — xxxAutoConfiguration — 容器中放入组件 — 绑定 xxxProperties — 配置项

springboot 启动过程原理

  • 创建 SpringApplication
    • 保存一些信息
    • 判断当前应用的类型,ClassUtils,Servlet
    • bootstrappers:初始启动引导器(List):去 spring.factories 文件中找
      org.springframework.boot.Bootstrapper
    • 找 ApplicationContextInitializer,去 spring.factories 找 ApplicationContextInitializer
    • 找 ApplicationListener,应用监听器,去 spring.factories 找 ApplicationListener
  • 运行 SpringApplication
    • StopWatch
    • 记录应用启动时间
    • 记录引导上下文(Context 环境)createBootstrapContext()
    • 让当前应用进入 headless 模式
    • 获取所有 RunListener(运行监听器)
    • 遍历 SpringApplicationRunListener 调用 starting 方法
    • 保存命令行参数 ApplicationArguments
    • 准备环境 prepareEnvironment()
    • 创建 IOC 容器(createApplicationContext())
    • 准备 ApplicationContext IOC 容器的基本信息
    • 刷新 IOC 容器 refreshContext
    • 所有监听器调用 listeners.started(context) 通知所有的监听器 started
    • 调用所有的 runners callRunners()
    • 调用所有监听器的 running 方法 listeners.running(context) 通知所有的监听器 running
    • running 如果有问题,继续通知 failed,调用所有 Listener 的 failed,通知所有的监听器 running

虚拟化技术

安全控制

缓存技术

消息中间件

分布式入门

响应式编程基础

webflux开发web应用

11、同步 servlet

一个请求进来,服务器启用一个 servlet 线程来进行处理,业务代码执行时,整个线程处于阻塞状态

12、异步 servlet

一个请求进来,业务代码交给线程池处理,servlet 线程可以去处理下一个请求,从而达到高的并发量

响应式访问持久化层

响应式安全开发

响应式原理

  • Copyrights © 2022-2023 hqz

请我喝杯咖啡吧~

支付宝
微信