当前位置 博文首页 > 攻城狮Chova:微服务架构学习Day01-SpringBoot入门

    攻城狮Chova:微服务架构学习Day01-SpringBoot入门

    作者:攻城狮Chova 时间:2021-02-10 14:29

    基本概念

    • SpringBoot的优点:
      • 可以创建独立的Spring应用
      • SpringBoot嵌入Tomcat,JettyUnsertow, 不需要部署war文件
      • 根据需要通过maven获取starter
      • Spring进行自动配置
      • 提供生产就绪型功能,包括指标,健康检查和外部配置

    SpringBoot父项目

    <parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-dependencies</artifactId>
    		<version>1.5.9.RELEASE</version>
    		<relativePath>../../spring-boot-dependencies</relativePath>
    	</parent>
    
    • 管理SpringBoot应用里面所有的依赖版本,这样以后导入依赖默认不需要写版本号,可以统一管理开发版本(没有在dependencies里面管理的依赖才需要声明版本号)

    spring-boot-starter

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
             </dependency>
    
    • spring-boot-starter: springboot场景启动器
    • spring-boot-starter-web: 导入web模块正常运行所依赖的组件
    • SpringBoot将所有的功能场景都抽取出来,做成各个starter启动器,只需要在项目的pom.xml中引入这些starter依赖,相关场景的所有依赖都会被导入进来。

    @SpringBootApplication

    • @SpringBootApplication:标注在SpringBoot的主配置类,SpringBoot就会运行这个类的main方法来启动SpringBoot运用。
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration 	//SpringBoot配置类,类似于配置文件。配置类也是容器中的组件。标注在类上标明是一个SpringBoot配置类
    @EnableAutoConfiguration	//开启SpringBoot自动配置功能
    @ComponentScan(
        excludeFilters = {@Filter(
        type = FilterType.CUSTOM,
        classes = {TypeExcludeFilter.class}
    ), @Filter(
        type = FilterType.CUSTOM,
        classes = {AutoConfigurationExcludeFilter.class}
    )}
    )
    public @interface SpringBootApplication {
        @AliasFor(
            annotation = EnableAutoConfiguration.class,
            attribute = "exclude"
        )
        Class<?>[] exclude() default {};
    
        @AliasFor(
            annotation = EnableAutoConfiguration.class,
            attribute = "excludeName"
        )
        String[] excludeName() default {};
    
        @AliasFor(
            annotation = ComponentScan.class,
            attribute = "basePackages"
        )
        String[] scanBasePackages() default {};
    
        @AliasFor(
            annotation = ComponentScan.class,
            attribute = "basePackageClasses"
        )
        Class<?>[] scanBasePackageClasses() default {};
    }
    
    • @SpringBootConfiguration: SpringBoot配置类,类似于配置文件。配置类也是容器中的组件。标注在类上标明是一个SpringBoot配置类
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration	// 表明该类是一个Spring的配置类
    public @interface SpringBootConfiguration {
    	@AliasFor(
    		annotation = Configuration.class
    	)
    	boolean proxyBeanMethods() default true;
    }
    
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component	// 表明该类是Spring的一个组件
    public @interface Configuration {
    	@AliasFor(
    		annotation = Component.class
    	)
    	String value default "";
    	
    	boolean proxyBeanMethods() default true; 
    }
    
    • @EnableAutoConfiguration: 开启SpringBoot自动配置功能
    
    package org.springframework.boot.autoconfigure;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import org.springframework.context.annotation.Import;
    
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {
        String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
        Class<?>[] exclude() default {};
    
        String[] excludeName() default {};
    }
    
    
    
    • @AutoConfigurationPackage: 自动配置包,通过 @Import({Registrar.class}) 完成,通过查看Registrar源码发现将主配置类即 @SpringBootApplication标注的类的所在包及所有子包里面的所有组件扫描到Spring容器中
    • 其中,@Import是Spring的底层注解,给容器导入一个组件,导入的组件由Registrar.class来指定。
    • AutoConfigurationImportSelector:导入组件的选择器,将所有需要导入的组件以全类名的方式返回,这样组件就会被添加到容器中
      • 会给容器中导入自动配置类:就是给容器中导入场景所有的组件并配置好.这样就不用手动编写配置并注入功能组件
    • SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader):
      • 从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
    • 过程总结:
      • SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值
      • 将这些值作为自动配置类导入到容器中,自动配置类就会生效,进行配置工作。
    • J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-2.0.1.RELEASE.jar中

    在SpringBoot项目中的resources文件夹:

    • static:保存所有静态资源,例如 js,css,images
    • templates:保存所有的模板页面。在SpringBoot中默认jar包使用的是嵌入式tomcat,默认不支持jsp页面。可以使用模板引擎:freemarker,thymeleaf
    • application.properties:SpringBoot应用的配置文件,可以修改一些默认设置

    SpringBoot配置

    配置文件

    SpringBoot使用一个全局配置文件,配置文件名是固定的:

    • application.properties
    • application.yml
    • 配置文件作用:修改SpringBoot自动配置的默认值。

    yml

    • yml:(YAML Ain't Markup Language)以数据为中心,比json、xml等更适合做配置文件。
    YAML基本语法
    • key: value(表示一对键值对。value前面必须要有空格。)
    • 空格缩进来表示层级关系,只要是左对齐的一列数据,都是同一个层级的
      1.缩进时不允许使用Tab键,只允许使用空格
      2.缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
    • 属性和值是大小写敏感
    • 值的写法:
      • 字面量:普通的值(数字,字符串,布尔值)
    • key:value :字面量直接书写。字符串默认不加引号。
    • 单引号-转义字符会作为普通字符串输出
    • 双引号-转义字符会转变成格式
    • 对象、Map(属性和值,键值对):
      • 对象还是key: value的方式
    friends:
              lastName: Chova
              firstName: Vea
    

    行内写法:

    friends: {lastName: Chova,firstName: Vea}
    
    • 数组(List、Set)
      • - 值表示数组中的元素
    pets:
      - dog
      - cat
      - pig
    

    行内写法:

    pets: [dog,cat,pig]
    

    @Value获取值和@ConfigurationProperties获取值比较

    @Value @ConfigurationProperties
    功能 在属性上一个一个指定注入 批量注入配置文件中的属性
    松散绑定(松散语法) 不支持 支持
    SpEL 支持 不支持
    JSR303数据校验 不支持 支持
    复杂类型封装 不支持 支持
    • 如果我们只是在某个业务逻辑中需要获取一下配置文件的某项值,就使用@Value
    • 如果JavaBean需要和配置文件进行映射,就使用@ConfigurationProperties

    配置文件注入值数值校验(JSR303)

    • 必须要用 @ConfigurationProperties
    • JSR303数据校验:@Validate-@Email

    @PropertySource和@ImportResource

    • @PropertySource:加载指定的配置文件
    @PropertySource(value = {"classpath:person.properties"})
    
    • @ImportResource:导入Spring的配置文件,让配置文件的内容生效
    @ImportResource(locations={"classpath:beans.xml"})
    
    • SpringBoot推荐给容器中添加组件的方式: 推荐使用 全注解 的方式
      1.配置类 --- Spring配置文件
      2.使用 @Bean在配置类中为容器中添加组件

    配置文件占位符

    • RandomValuePropertySource:配置文件中可以使用随机数
    1.${random.value}
    2.${random.int}
    3.${random.int(10)}
    4.${random.int[1024,65536]}
    
    • 属性配置占位符
      1.可以在配置文件中引用前面配置过的属性(优先级前面配置过的这里都能用)
      2.${app.name:默认值}来指定找不到属性值时的默认值

    Profile

    • 多Profile文件
      1.在写配置文件的时候,文件名可以是:application-{profile}.properties/yml
      2.默认使用application.properties的配置
    • yml支持多文档块方式
      • 用"- - -"划分文档块
    ---
    

    激活指定Profile
    1.在主配置文件application.properties中指定激活:

    spring.profiles.active=dev
    

    2.命令行激活:(Program arguments)

    --spring.profiles.active=dev
    

    3.虚拟机参数激活:(VM options)

    -Dspring.profiles.active=dev
    

    配置文件加载位置

    • SpringBoot启动会扫描以下位置的application.properties或者application.yml文件作为SpringBoot的默认配置文件
    1. file:./config/
    2. file:./
    3. classpath:/config
    4. classpath:/
    • 以上按照优先级从高到低,所有文件都会被加载,互补配置。高优先级内容会覆盖低优先级内容。
    • 可以通过配置- -spring.config.location来改变默认配置位置:项目打包好以后,使用命令行参数的形式,启动项目的时候来指定配置文件的新位置,指定的配置文件和默认加载的配置文件会共同起作用,互补配置。

    外部配置的加载顺序

    • SpringBoot支持多种外部配置方式,优先级如下:
      1.命令行参数(- -,多个命令用空格分开)
      2.来自java:comp/env的JNDI属性
      3.Java系统属性(System.getProperties())
      4.操作系统环境变量
      5.RandomValuePropertySource配置的random.*属性值
      由jar包外部向jar包内进行寻找:
      优先加载带profile的:
      6.jar包外部的application-{profile}.properties/yml(带spring.profile)配置文件
      7.jar包内部的application-{profile}.properties/yml(带spring.profile)配置文件
      然后加载不带Profile的:
      8.jar包外部的application-{profile}.properties/yml(不带spring.profile)配置文件
      9.jar包内部的application-{profile}.properties/yml(不带spring.profile)配置文件
      10.@Configuration注解类上的@PropertySource
      11.通过SpringApplication.setDefaultProperties指定的默认属性

    自动配置原理

    • SpringBoot启动时加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
    • @EnableAutoConfiguration作用:利用EnableAutoConfigurationImportSelector给容器导入组件。
      具体实现可以查看selectImports() 方法:
    List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置
    SpringFactoriesLoader.loadFactoryNames();扫描所有jar包类路径下:META-INF/spring.factories。把扫描到的这些文件的内容包装成properties对象,从properties中获取到EnableAutoConfiguration.class(类名)类的值,然后把它们添加在容器中
    

    将类路径下META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到了容器中。

    • 每一个自动配置类进行自动配置功能。
    @Configuration	// 表示这是一个配置类,类似配置文件,可以给容器中添加组件
    @EnableConfigurationProperties({HttpProperties.class})	// 启用指定类的ConfigurationProperties(从配置文件中获取指定的值和bean的属性进行绑定)功能
    @ConditionalOnWebApplication(	// Spring底层@conditional注解,根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效(判断当前应用是否为web应用)
       type = Type.SERVLET
    )
    @ConditionalOnClass({CharacterEncodingFilter.class})	// 判断当前项目有没有这个类,CharacterEncodingFilter:SpringMVC中进行乱码解决的过滤器
    @ConditionalOnProperty(	// 判断文件中是否存在某个配置
       prefix = "spring.http.encoding",
       value = {"enabled"},
       matchIfMissing = true	// 即使配置文件中不配置spring.http.encoding.enable=true,也是默认生效的
    )
    public class HttpEncodingAutoConfiguration {
    

    根据当前不同的条件判断,决定配置类是否生效,就会通过@Bean为容器中添加各种组件,这些组件的值需要从properties中获取,properties中的每一个属性和配置文件绑定。
    注意点:

    • @Conditional派生注解(来源于Spring底层注解@Conditional)
      1.作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置里面的所有内容才生效。
      2.自动配置类必须在一定的条件下才会生效:在配置文件中
    	debug=true
    

    可以在控制台打印自动配置报告,可以查看哪些自动配置生效,哪些自动配置不生效。

    总结

    • SpringBoot启动会加载大量的自动配置类。
    • 判断SpringBoot默认写好的自动配置类有没有需要的功能。
    • 判断自动配置类是否配置需要的组件,没有的就需要自己配置。
    • 给容器中自动配置类添加组件时,会从properties中获取属性,在配置文件中指定这些属性的值。
    • xxAutoConfiguration:自动配置类,给容器中添加组件===xxProperties:封装配置文件中的相关属性,和配置文件绑定
    bk