Java - 框架之 SpringBoot 攻略day01

时间:2021-02-18 14:46:41
 
 
 

Spring-Boot 攻略 day01

spring-boot


 

一. 基本配置加运行

 

1. 导入配置文件(pom.xml 文件中)

 
  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version>1.5.9.RELEASE</version>
  5. </parent>
  6. <dependencies>
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-web</artifactId>
  10. </dependency>
  11. </dependencies>
 

2. Application.java

 
  1. @SpringBootApplication
  2. publicclassHelloApplication{
  3. publicstaticvoid main(String[] args){
  4. SpringApplication.run(HelloApplication.class, args);
  5. }
  6. }
 

3. Controller.java

 
  1. /*
  2. @RestController 可以代替 @ResponseBody 和 @Controller
  3. */
  4. @ResponseBody
  5. @Controller
  6. publicclass h1Controller {
  7. @RequestMapping("/hello")
  8. publicString t1(){
  9. return"Hello!";
  10. }
  11. }
 

4. 直接运行 Application 中的代码,页面访问 http://localhost:8080/hello 就会看到 Hello!。

 

5. 打包 jar 包,在 pom.xml 配置文件中添加:

 
  1. <!-- 这个插件,可以将应用打包成一个可执行的jar包;-->
  2. <build>
  3. <plugins>
  4. <plugin>
  5. <groupId>org.springframework.boot</groupId>
  6. <artifactId>spring-boot-maven-plugin</artifactId>
  7. </plugin>
  8. </plugins>
  9. </build>
 

6.运行:

java -jar jar包名

 

二. SpringBoot( pom.xml )文件讲解

 

1. 依赖包:

都存放在 pom.xml 文件 -> spring-boot-starter-parent -> spring-boot-dependedcies 中
 

2. 启动器

spring-boot-starter: Spring-Boot 场景启动器。
比如上面的 **spring-boot-starter-web**就帮我们导入了有关web项目的启动器, 所以需要什么场景的starter(启动器),只需要导入相关依赖即可。
 
  1. <artifactId>spring-boot-starter-web</artifactId>
 

三. 主程序(主入口)类

 

1. 注解

@SpringBootApplication :标注在某个类上说明这个类是 SpringBoot 的主配置类,SpringBoot 可以运行这个类的 main 方法来启动服务。

 
  1. @SpringBootApplication
  2. publicclassHelloApplication{
  3. publicstaticvoid main(String[] args){
  4. SpringApplication.run(HelloApplication.class, args);
  5. }
  6. }

@SpringBootConfiguration :Spring Boot的配置类;

@Configuration :配置类标注这个注解(配置文件;配置类也是容器中的一个组件;@Component)

@EnableAutoConfiguration :开启自动配置功能;

@AutoConfigurationPackage :自动配置包;

@Import(EnableAutoConfigurationImportSelector.class) : 给容器中导入组件;

 

四. 使用 Spring Initializer 快速创建 Spring Boot 项目

 

1. 创建 Spring Initializer 项目,并选择需要使用的模块。

 

2. resources 文件夹中目录结构

  • static : 静态资源
  • templates :模板页面
  • application.properties : SpringBoot 应用的配置文件
 

五. 配置文件(两者都可配置,写法不同)

 

1. application.properties

  • 写法:
 
  1. server.port=8081
 

2. application.yml (默认没有,需手动创建到 resources 文件下)

  • 写法
 
  1. server:
  2. port:8081
 

3. YMAL 基本语法

  • 以空格缩进
 
  1. server:
  2. port:8081
  • 值的写法

    • 字面量:k: v 的方式来写(注意有个空格在:的后面)

      "" :双引号不会转义特殊字符
      '' : 单引号会转移特殊字符(转义为字符串)

  • 对象,Map 写法

    1. k: v 与上面写法一致

      1. server:
      2. port:8081
    2. 行内表示:

      1. server:{port:8081}
  • 数组 (List, Set)

 
  1. Person:
  2. - p1
  3. - p2
  4. - p3
 

4. 配置文件的注入

 

注意:这个配置顺序要写在单元测试配置之前

 
  1. <!--导入配置文件处理器,配置文件进行绑定就会有提示-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-configuration-processo</artifactId>
  5. <optional>true</optional>
  6. </dependency>
 

一. yaml 配置

  • application.yml
 
  1. lastname:张三
  2. age:11
  3. isBoy:true
  4. Date:2019/4/19
  5. maps:{k1: v1, k2:59}
  6. lists:
  7. - li1
  8. - li2
  9. dog:
  10. name:黑狗
  11. age:1
  • Person.java
 
  1. /*
  2. * 将配置文件中配置的每一个属性值,映射到这个组件中
  3. * @ConfigurationProperties:告诉 SpringBoot 将当前类中的所有属性与 配置文件中的配置进行帮定
  4. * prefix = "person" : 配置文件中哪个下面的所有属性进行映射
  5. *
  6. * 只有这个组件是容器中的组件,才能提供 @ConfigurationProperties 中的功能,也就是需要加上:@Component
  7. * */
  8. @Component
  9. @ConfigurationProperties(prefix ="person")
  10. publicclassPerson{
  11. privateString lastName;
  12. privateInteger age;
  13. privateBoolean isBoy;
  14. privateDate birthday;
  15. privateMap<Object,Object> maps;
  16. privateList<Object> lists;
  17. privateDog dog;
  18. }
  • Dog.java
 
  1. publicclassDog{
  2. privateString name;
  3. privateInteger age;
  4. }
  • Test 单元测试
 
  1. @Autowired
  2. Person person;
  3. @Test
  4. publicvoid contextLoads(){
  5. System.out.println(person);
  6. }
 

二. properties 配置 ( application.properties )

 

注意:使用这个配置会有编码问题,解决如下( idea ):

settings -> File Encodings 配置下:

Default encoding for properties files: 设置为 UTF-8
勾选:Transparent native-to-ascii conversion 这个选项

  • application.properties 文件
 
  1. # 配置 Person 的值
  2. person.last-name=张三
  3. person.age=11
  4. person.birthday=2019/4/19
  5. person.isBoy=true
  6. person.maps.k1=v1
  7. person.maps.k2=59
  8. person.lists=p1,p2,p3
  9. person.dog.name=大黑狗
  10. person.dog.age=2
  • 剩余配置如上
 

三. @ConfigurationProperties 与 @Value

比较 @ConfigurationProperties @Value
功能 批量注入配置文件中的属性 一个个指定
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持
  • 松散绑定 :如果遇到 last-name 可以写成 lastName,也就是带有 - 或 _ 的后一个字母可用大写
  • SpEL : 语法解析,如 ${1*19} , @Value 就可以解析
  • JSR303数据校验 : 内置的 @Eamil 等可以进行数据的校验,详细请看下文
  • 复杂类型封装 :如 Map 等复杂类型 @Value 是无法解析的(List可以解析),会报错
 
  1. @Component
  2. //@ConfigurationProperties(prefix = "person")
  3. @Validated
  4. publicclassPerson{
  5. // @Value("${person.last-name}")
  6. @Email// 这里 lastName 必须是邮箱格式
  7. privateString lastName;
  8. @Value("#{1*10}")// 可进行逻辑操作
  9. privateInteger age;
  10. privateBoolean isBoy;
  11. privateDate birthday;
  12. privateMap<Object,Object> maps;
  13. privateList<Object> lists;
  14. privateDog dog;
  15. }
 

四. @PropertySource & @ImportResource & @Bean

@PropertySource:加载指定的配置文件;

 
  1. /**
  2. *
  3. * @PropertySource : 可以指定到去哪个文件加载配置
  4. */
  5. @PropertySource(value ={"classpath:person.properties"})
  6. @Component
  7. @ConfigurationProperties(prefix ="person")
  8. //@Validated
  9. publicclassPerson{
  10. /**
  11. * <bean class="Person">
  12. * <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#{SpEL}"></property>
  13. * <bean/>
  14. */
  15. //lastName必须是邮箱格式
  16. // @Email
  17. //@Value("${person.last-name}")
  18. privateString lastName;
  19. //@Value("#{11*2}")
  20. privateInteger age;
  21. //@Value("true")
  22. privateBoolean boss;
  23. }

@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;

Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;

想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上

 
  1. @ImportResource(locations ={"classpath:beans.xml"})
  2. 导入Spring的配置文件让其生效

使用XML文件加载配置(beans.xml)

 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5. <beanid="helloService"class="com.atguigu.springboot.service.HelloService"></bean>
  6. </beans>

SpringBoot推荐给容器中添加组件的方式:使用全注解

1、配置类@Configuration------>Spring配置文件

2、使用@Bean给容器中添加组件

  • Service.java
 
  1. // @Configuration :指明当前类为配置类,用来替代 Spring 配置文件
  2. @Configuration
  3. publicclassMyAppConfig{
  4. // @Bean :将方法的返回值添加到容器中,容器中这个组件的默认id就是方法名
  5. @Bean
  6. publicHelloService helloService(){
  7. returnnewHelloService();
  8. }
  9. }
  • 单元测试类
 
  1. @Autowired
  2. ApplicationContext ioc;
  3. @Test
  4. publicvoid testHelloService(){
  5. System.out.println("执行配置文件...");
  6. boolean b = ioc.containsBean("helloService");
  7. System.out.println(b);
  8. }
 

五. 配置文件占位符

 

1、随机数

 
  1. ${random.value}、${random.int}、${random.long}
  2. ${random.int(10)}、${random.int[1024,65536]}
 

2、占位符获取之前配置的值,如果没有可以是用:指定默认值

 
  1. person.last-name=张三${random.uuid}
  2. person.age=${random.int}
  3. person.birth=2017/12/15
  4. person.boss=false
  5. person.maps.k1=v1
  6. person.maps.k2=14
  7. person.lists=a,b,c
  8. person.dog.name=${person.hello:hello}_dog
  9. person.dog.age=15
 

六. Profile

 

1、多Profile文件

我们在主配置文件编写的时候,文件名可以是 application-{profile}.properties/yml

默认使用application.properties的配置;

 

2、yml支持多文档块方式

 
  1. server:
  2. port:8081
  3. spring:
  4. profiles:
  5. active: prod
  6. ---
  7. server:
  8. port:8083
  9. spring:
  10. profiles: dev
  11. ---
  12. server:
  13. port:8084
  14. spring:
  15. profiles: prod #指定属于哪个环境
 

3、激活指定profile

​ 1、在配置文件中指定 spring.profiles.active=dev

​ 2、命令行:

​ java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;

​ 可以直接在测试的时候,配置传入命令行参数

​ 3、虚拟机参数;

​ -Dspring.profiles.active=dev

 

七、配置文件加载位置

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

–file:./config/

–file:./

–classpath:/config/

–classpath:/

优先级由高到底,高优先级的配置会覆盖低优先级的配置;

SpringBoot会从这四个位置全部加载主配置文件;互补配置

==我们还可以通过spring.config.location来改变默认的配置文件位置==

项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties

 

八、外部配置加载顺序

==SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置==

1.命令行参数

所有的配置都可以在命令行上进行指定

java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc

多个配置用空格分开; --配置项=值

2.来自java:comp/env的JNDI属性

3.Java系统属性(System.getProperties())

4.操作系统环境变量

5.RandomValuePropertySource配置的random.*属性值

==由jar包外向jar包内进行寻找;==

==优先加载带profile==

6.jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件

7.jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件

==再来加载不带profile==

8.jar包外部的application.properties或application.yml(不带spring.profile)配置文件

9.jar包内部的application.properties或application.yml(不带spring.profile)配置文件

10.@Configuration注解类上的@PropertySource

11.通过SpringApplication.setDefaultProperties指定的默认属性

所有支持的配置加载来源;

参考官方文档

 

8、自动配置原理

配置文件到底能写什么?怎么写?自动配置原理;

配置文件能配置的属性参照

 

1、自动配置原理:

1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能 ==@EnableAutoConfiguration==

2)、@EnableAutoConfiguration 作用:

  • 利用EnableAutoConfigurationImportSelector给容器中导入一些组件?

    • 可以查看selectImports()方法的内容;

    • List configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置

    1. SpringFactoriesLoader.loadFactoryNames()
    2. 扫描所有jar包类路径下 META-INF/spring.factories
    3. 把扫描到的这些文件的内容包装成properties对象
    4. 从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中

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

 
  1. # Auto Configure
  2. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  3. org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
  4. org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
  5. org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
  6. org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
  7. org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
  8. org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
  9. org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
  10. org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
  11. org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
  12. org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
  13. org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
  14. org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,
  15. ...

每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;

3)、每一个自动配置类进行自动配置功能;

4)、以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

 
  1. @Configuration//表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
  2. @EnableConfigurationProperties(HttpEncodingProperties.class)//启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中
  3. @ConditionalOnWebApplication//Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效; 判断当前应用是否是web应用,如果是,当前配置类生效
  4. @ConditionalOnClass(CharacterEncodingFilter.class)//判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;
  5. @ConditionalOnProperty(prefix ="spring.http.encoding", value ="enabled", matchIfMissing =true)//判断配置文件中是否存在某个配置 spring.http.encoding.enabled;如果不存在,判断也是成立的
  6. //即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
  7. publicclassHttpEncodingAutoConfiguration{
  8. //他已经和SpringBoot的配置文件映射了
  9. privatefinalHttpEncodingProperties properties;
  10. //只有一个有参构造器的情况下,参数的值就会从容器中拿
  11. publicHttpEncodingAutoConfiguration(HttpEncodingProperties properties){
  12. this.properties = properties;
  13. }
  14. @Bean//给容器中添加一个组件,这个组件的某些值需要从properties中获取
  15. @ConditionalOnMissingBean(CharacterEncodingFilter.class)//判断容器没有这个组件?没有才加载
  16. publicCharacterEncodingFilter characterEncodingFilter(){
  17. CharacterEncodingFilter filter =newOrderedCharacterEncodingFilter();
  18. filter.setEncoding(this.properties.getCharset().name());
  19. filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
  20. filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
  21. return filter;
  22. }

根据当前不同的条件判断,决定这个配置类是否生效?

一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;

5)、所有在配置文件中能配置的属性都是在xxxxProperties类中封装者‘;配置文件能配置什么就可以参照某个功能对应的这个属性类

 
  1. @ConfigurationProperties(prefix ="spring.http.encoding")//从配置文件中获取指定的值和bean的属性进行绑定
  2. publicclassHttpEncodingProperties{
  3. publicstaticfinalCharset DEFAULT_CHARSET =Charset.forName("UTF-8");

精髓:

1)、SpringBoot启动会加载大量的自动配置类

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

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

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

xxxxAutoConfigurartion:自动配置类;

给容器中添加组件

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

 

2、细节

 

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

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

@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项

自动配置类必须在一定的条件下才能生效;

我们怎么知道哪些自动配置类生效;

==我们可以通过启用 debug=true属性;来让控制台打印自动配置报告==,这样我们就可以很方便的知道哪些自动配置类生效;

 
  1. =========================
  2. AUTO-CONFIGURATION REPORT
  3. =========================
  4. Positive matches:(自动配置类启用的)
  5. -----------------
  6. DispatcherServletAutoConfiguration matched:
  7. -@ConditionalOnClass found required class'org.springframework.web.servlet.DispatcherServlet';@ConditionalOnMissingClass did not find unwanted class(OnClassCondition)
  8. -@ConditionalOnWebApplication(required) found StandardServletEnvironment(OnWebApplicationCondition)
  9. Negative matches:(没有启动,没有匹配成功的自动配置类)
  10. -----------------
  11. ActiveMQAutoConfiguration:
  12. Did not match:
  13. -@ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory','org.apache.activemq.ActiveMQConnectionFactory'(OnClassCondition)
  14. AopAutoConfiguration:
  15. Did not match:
  16. -@ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect','org.aspectj.lang.reflect.Advice'(OnClassCondition)