SpringBoot

1. 第一个springBoot程序

在这里插入图片描述

文件目录一定要跟XXXAppplication同级。

springboot每个项目打成jar包可以独立运行。

java -jar jar包的名字

2. 原理初探

自动配置

pom.xml
  • spring-boot-dependencies 这是核心依赖,在父工程中。
  • 我们在引入springboot依赖时不用写版本,就是因为有这些版本仓库
启动器
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • 启动器:就是springboot的启动场景
  • 比如spring-boot-starter-web,会帮我们自动导入web环境所有的依赖!
  • springboot会将所有的功能场景, 变成一个个启动器
  • 我们要使用什么功能,就只需找到对应的启动器
主程序
@SpringBootApplication
public class Springboot01HelloworldApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot01HelloworldApplication.class, args);
    }

}
  • 注解

    • @SpringBootConfiguration :springboot的配置
      	@Configuration : spring配置
      		@Component : spring组件
      
      
      @EnableAutoConfiguration :自动配置
      	@AutoConfigurationPackage : 自动配置包
      		@Import({Registrar.class}) 自动配置,包注册
      	@Import({AutoConfigurationImportSelector.class}) :自动配置导入选择器,
      
      

      AutoConfigurationImportSelector这个类中有如下方法getCandidateConfigurations

      1. 获取候选的配置
      // 获取候选的配置
      protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
              List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
              Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
              return configurations;
          }
      
      2.这个类又调用了 SpringFactoriesLoader 类的静态方法
      public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
          String factoryClassName = factoryClass.getName();
          //这里它又调用了 loadSpringFactories 方法
          return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
      }
      
      3.我们继续点击查看 loadSpringFactories 方法
      private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
          //获得classLoader , 我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身
          MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
          if (result != null) {
              return result;
          } else {
              try {
                  //去获取一个资源 "META-INF/spring.factories"
                  Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                  LinkedMultiValueMap result = new LinkedMultiValueMap();
      
                  //将读取到的资源遍历,封装成为一个Properties
                  while(urls.hasMoreElements()) {
                      URL url = (URL)urls.nextElement();
                      UrlResource resource = new UrlResource(url);
                      Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                      Iterator var6 = properties.entrySet().iterator();
      
                      while(var6.hasNext()) {
                          Entry<?, ?> entry = (Entry)var6.next();
                          String factoryClassName = ((String)entry.getKey()).trim();
                          String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                          int var10 = var9.length;
      
                          for(int var11 = 0; var11 < var10; ++var11) {
                              String factoryName = var9[var11];
                              result.add(factoryClassName, factoryName.trim());
                          }
                      }
                  }
      
                  cache.put(classLoader, result);
                  return result;
              } catch (IOException var13) {
                  throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
              }
          }
      }
      
      4.发现一个多次出现的文件:spring.factories,找到它

在这里插入图片描述

spring.factories

我们根据源头打开spring.factories , 看到了很多自动配置的文件;这就是自动配置根源所在!

在这里插入图片描述
结论:
  1. SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值

  2. 将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;

  3. 整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;

  4. 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件 ;

  5. 有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;

SpringApplication.run分析

run方法流程

图片

3. properties配置文件

server.port=8088  # 端口号
server.servlet.context-path=/dingtalkbot  # 项目后缀


# 整合redis
spring.redis.host=172.16.21.139   
spring.redis.database=7
spring.redis.port=17001


#放开springboot对静态资源的拦截
spring.mvc.static-path-pattern:/**  # 项目路径
spring.resources.static-locations:classpath:/**   # 资源路径下

4. yml属性注入

实体类 Person.class
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
   private String name;
   private Integer age;
   private Boolean happy;
   private Date date;
   private Map<String,Object> maps;
   private List<Object> list;
   private Dog dog;
   ...
   ...
application.yml
person:
  name: zhulianwei
  age: 3
  happy: false
  birth: 2000/01/01
  maps: {k1: v1,k2: v2}
  list:
    - code
    - girl
    - music
  dog:
    name: 旺财
    age: 1

5. 一些注解

@ConfigurationProperties 默认从全局配置文件中获取值

@

6. JSR303校验

一种属性注入的数据校验

@Validated // 数据校验
public class Person {
    @Email()
    private String name;

比如实体类中的**@Email**注解,在给name赋值的时候,只能是email格式,否则报错。

常见参数
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;

空检查
@Null       验证对象是否为null
@NotNull    验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank   检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty   检查约束元素是否为NULL或者是EMPTY.
    
Booelan检查
@AssertTrue     验证 Boolean 对象是否为 true  
@AssertFalse    验证 Boolean 对象是否为 false  
    
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内  
@Length(min=, max=) string is between min and max included.

日期检查
@Past       验证 Date 和 Calendar 对象是否在当前时间之前  
@Future     验证 Date 和 Calendar 对象是否在当前时间之后  
@Pattern    验证 String 对象是否符合正则表达式的规则

.......等等
除此以外,我们还可以自定义一些数据校验规则

7. 多环境配置以及配置文件位置

配置文件加载位置

外部加载配置文件的方式十分多,我们选择最常用的即可,在开发的资源文件中进行配置!

springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件:

优先级1:项目路径下的config文件夹配置文件优先级2:项目路径下配置文件优先级3:资源路径下的config文件夹配置文件优先级4:资源路径下配置文件
yml的多环境配置

以下配置了三套环境,默认/dev/test,在yml中只需要用’—'来分隔开,用spring profiles来标识选择哪一套配置。

server:
  port: 8081
#选择要激活那个环境块
spring:
  profiles:
    active: test

---
server:
  port: 8083
spring:
  profiles: dev #配置环境的名称


---

server:
  port: 8084
spring:
  profiles: test  #配置环境的名称

8. 自动装配原理

https://www.cnblogs.com/javaguide/p/springboot-auto-config.html

1 主程序

@SpringBootApplication // ★★★
public class Springboot01HelloworldApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot01HelloworldApplication.class, args);
    }

}

2 SpringBootApplication注解

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration@EnableAutoConfiguration // ★★★@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication {    ...}

3 EnableAutoConfiguration注解

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage // 作用:将main包下的所有组件注册到容器中 ★★★@Import(AutoConfigurationImportSelector.class) // ★★★public @interface EnableAutoConfiguration {    // ...}

4 AutoConfigurationImportSelector 类

AutoConfigurationImportSelector 类实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中

public String[] selectImports(AnnotationMetadata annotationMetadata) {
   // <1>.判断自动装配开关是否打开
   if (!isEnabled(annotationMetadata)) {
      return NO_IMPORTS;
   }
   //<2>.获取所有需要装配的bean
   AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); // ★★★
   return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

这里我们需要重点关注一下getAutoConfigurationEntry()方法,这个方法主要负责加载自动配置类的。

该方法调用链如下:

img
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    //<1>.
    if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
   }
   //<2>.
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
   //<3>.
   List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); // ★★★
   configurations = removeDuplicates(configurations);
   Set<String> exclusions = getExclusions(annotationMetadata, attributes);
   checkExcludedClasses(configurations, exclusions);
   configurations.removeAll(exclusions);
   //<4>.
   configurations = getConfigurationClassFilter().filter(configurations); // ★★★ 过滤
   fireAutoConfigurationImportEvents(configurations, exclusions);
   return new AutoConfigurationEntry(configurations, exclusions);
}
第一步

​ 判断自动装配开关是否打开。默认spring.boot.enableautoconfiguration=true,可在 application.propertiesapplication.yml 中设置

第二步

​ 用于获取EnableAutoConfiguration注解中的 excludeexcludeName

第三步 ★★★

​ 获取需要自动装配的所有配置类

  • getCandidateConfigurations
  • SpringFactoriesLoader
  • loadSpringFactories 读取META-INF/spring.factories ★★★★★★
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
...
第四步:

spring.factories中这么多配置,每次启动都要全部加载么?

不是的,这一步有经历了一遍筛选,@ConditionalOnXXX 中的所有条件都满足,该类才会生效。

原理再探究

META-INF/spring.factories其中的HttpEncodingAutoConfiguration

// 1. 表示这是一个配置类
@Configuration(proxyBeanMethods = false)

// 2. 自动配置属性,ServerProperties的属性可以在配置文件中配置
@EnableConfigurationProperties(ServerProperties.class)

// 3. spring的底层注解,根据不同的条件,来判断当前配置或者类是否生效 
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {

	private final Encoding properties;

	public HttpEncodingAutoConfiguration(ServerProperties properties) {
		this.properties = properties.getServlet().getEncoding();
	}

	@Bean
	@ConditionalOnMissingBean
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
	// ......

}
了解@Conditional

了解完自动装配的原理后,我们来关注一个细节问题,自动配置类必须在一定的条件下才能生效;

@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

在这里插入图片描述

那么多的自动配置类,必须在一定的条件下才能生效;也就是说,我们加载了这么多的配置类,但不是所有的都生效了。

  1. springboot帮我们自动装配
  2. 会从xxxProperties.class里面取默认值
  3. 可以在配置文件中修改值

精髓

1、SpringBoot启动会加载大量的自动配置类(spring.factories中的类)

2、我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中;

3、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)

4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;

**xxxxAutoConfiguration:自动配置类;**给容器中添加组件

xxxxProperties:封装配置文件中相关属性;

总结 ★★★★★★

​ Spring Boot 通过==@EnableAutoConfiguration==开启自动装配,

​ 通过 SpringFactoriesLoader 最终加载META-INF/spring.factories中的自动配置类实现自动装配。

​ 自动配置类要在==@Conditionalonxxx==注解条件满足下才能加载,

​ 想要其条件满足必须引入spring-boot-starter-xxx包实现起步依赖。

开发简单网站

一、静态资源过滤

​ 这四个目录下的静态资源都能直接访问到。静态资源都会从这4个目录中找。

在这里插入图片描述

项目目录结构

在这里插入图片描述

首页定制------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值