Spring Boot 学习笔记(1)

什么是 Spring?

 Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。Spring是一个开源框架,它由Rod Johnson创建。
目的是为了解决企业应用开发的复杂性而创建的。

Spring 如何简化 Java 开发的?

 为了降低Java开发的复杂性,Spring采用了以下4种关键策略:
 1、基于 POJO 的轻量级和最小侵入性编程;
 2、通过 IOC,依赖注入(DI)和面向接口实现松耦合;
 3、基于切面(AOP)和惯例进行声明式编程;
 4、通过切面和模版减少样式代码;

什么是 SpringBoot?

 SpringBoot是由Pivotal团队在2013年开始研发、2014年4月发布第一个版本的全新开源的轻量级框架。它基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。
其设计目的是用来简化新Spring应用的初始搭建以及开发过程。
SpringBoot框架中还有两个非常重要的策略:开箱即用和约定优于配置。

特征:

  • 可以创建独立的Spring应用程序
  • 内嵌Tomcat,Jetty或Undertow(无需部署WAR文件)
  • 提供自动配置的 “starter” 项目对象模型(POMS)以简化Maven配置
  • 尽可能自动配置 Spring 和第三方库
  • 提供准备好的特性,如指标、健康检查和外部化配置
  • 完全没有代码生成,也不需要XML配置

什么是微服务?(以后再学)

https://www.zhihu.com/question/65502802

一、SpringBoot 项目创建

官网创建:https://start.spring.io/
IDEA 创建:
在这里插入图片描述

pom.xml中的配置:

  • parent: 继承 spring-boot-starter-parent的依赖管理,控制版本与打包等内容
  • dependencies: 项目具体依赖,这里包含了
    • spring-boot-starter-web用于实现HTTP接口(该依赖中包含了Spring MVC),官网对它的描述是:使用 Spring MVC 构建Web(包括RESTful)应用程序的入门者,使用Tomcat作为默认嵌入式容器。
    • spring -boot-starter-test用于编写单元测试的依赖包。更多功能模块的使用我们将在后面逐步展开。
  • build:构建配置部分。默认使用了 spring-boot-maven-plugin,配合 spring-boot-starter-parent就可以把 Spring Boot 应用打包成 JAR 来直接运行。

测试

在主程序即 xxxApplication 同级目录下新建一个包 controller【一定要在同级目录下,否则识别不到】。

在这里插入图片描述

编写代码:

@RestController
public class HelloController {

    // 接口: http://localhost:8080/hello/
    @RequestMapping("/hello")
    public String hello(){
        // 调用业务,接收前端参数
        return "Hello SpringBoot!";
    }
}

启动主程序,并在浏览器中输入:http://localhost:8080/hello/ 测试。

彩蛋

在 resources 目录下新建 banner.txt
再去 bootschool 找ASCII艺术字(图)集写到 banner.txt
就可以修改 SpringBoot 的启动图标了

二、 原理初探

1、 SpringBoot 自动装配原理:

pom.xml

  • spring-boot-dependencies : 核心依赖在父工程中
    • 我们在写或者引入一些 SpringBoot 依赖的时候,不需要指定版本,就是因为有这些版本仓库。

启动器 :

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
</dependency>
  • 说白了就是 SpringBoot 的启动场景。
  • 比如 <artifactId>spring-boot-starter-web</artifactId>: 就会帮我们自动导入 web 环境所有的依赖。
  • SpringBoot 会将所有的功能场景,都变成一个个的启动器。
  • 如果我们要使用什么功能,就只需要找到对应的启动器就可以了。 “starter”

主程序

// @SpringBootApplication: 标注这个类是一个 SpringBoot 的应用。
 @SpringBootApplication
 public class Springboot01HelloworldApplication {

     public static void main(String[] args) {
         // 将 SpringBoot 启动
         SpringApplication.run(Springboot01HelloworldApplication.class, args);
     }
 }
  • 注解(Ctrl + 鼠标左键 点入)

>自行查阅<

注解的用途
原文链接:https://blog.csdn.net/yuzongtao/article/details/83306182

在看注解的用途之前,有必要简单的介绍下XML和注解区别,

  • 注解:是一种分散式的元数据,与源代码紧绑定。
  • xml:是一种集中式的元数据,与源代码无绑定

当然网上存在各种XML与注解的辩论哪个更好,这里不作评论和介绍,主要介绍一下注解的主要用途:

  • 生成文档,通过代码里标识的元数据生成javadoc文档。
  • 编译检查,通过代码里标识的元数据让编译器在编译期间进行检查验证。
  • 编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码。
  • 运行时动态处理,运行时通过代码里标识的元数据动态处理,例如使用反射注入实例。

@Import
@Import注解功能就是和Spring XML 里面 的 一样. @Import注解是用来导入配置类或者一些需要前置加载的类.

@Configuration
 从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被 AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext 类进行扫描,并用于构建bean定义,初始化Spring容器。


  • @SpringBootApplication : 组合注解
    • @SpringBootConfiguration : SpringBoot 的配置
      • @Configuration
        • @Component : 说明这也是一个 Spring 的组件
    • @EnableAutoConfiguration : 自动配置
      • @AutoConfigurationPackage : 自动配置包
        • @Import(AutoConfigurationPackages.Registrar.class) : 自动配置 包注册
      • @Import(AutoConfigurationImportSelector.class) : 自动配置导入选择
    • @ComponentScan : 扫描当前主启动类同级的包

自动配置导入选择 : AutoConfigurationImportSelector 类下的 selectImports() 方法调用的 getAutoConfigurationEntry() 方法中:

// 获取所有的配置。
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); 

获取候选的配置

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
            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;
}

META-INF/spring.factories : 自动配置的核心文件

在这里插入图片描述


在这里插入图片描述

自动配置真正实现是从 classpath 中搜寻所有的 META-INF/spring.factories 配置文件,并将其中对应的 org.springframework.boot.autoconfigure.包下的配置项,通过反射实例化为对应标注了 @Configuration 的 JavaConfig 形式的IOC容器配置类,然后将这些都汇总成为一个实例并加载到IOC容器中。

结论:
springboot 所有自动配置都是在启动的时候扫描并加载: spring.factories 所有的自动配置类都在这里面,但是不一定生效:要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功!

  1. SpringBoot在启动的时候从类路径下的 META-INF/spring.factories 中获取 EnableAutoConfiguration 指定的值
  2. 将这些值作为自动配置类导入容器,自动配置类就生效,帮我们进行自动配置工作;
  3. 以前我们需要自己配置的东西,自动配置类都帮我们解决了
  4. 整个J2EE的整体解决方案和自动配置都在 springboot-autoconfigure.jar 包中;
  5. 它将所有需要导入的组件以全类名的方式返回,这些组件就会被添加到容器中;
  6. 它会给容器中导入非常多的自动配置类(xxxAutoConfiguration),就是给容器中导入这个场景需要的所有组件,并配置好这些组件. @Configuration > JavaConfig!
  7. 有了自动配置类,免去了我们手动编写配置注入功能组件等的工作;
2、 主启动类运行
@SpringBootApplication
public class Springboot01HelloworldApplication {

    public static void main(String[] args) {
        // 该方法返回一个 configurableApplicationContext 对象
        // 参数一:应用入口的类 参数二:命令行参数
        SpringApplication.run(Springboot01HelloworldApplication.class, args);
    }
}

SpringApplication.run 分析分为两部分:一是 SpringApplication 实例化,二是 run 方法执行。

SpringApplication

这个类主要做了以下四件事情

  1. 推断应用的类型是普通的项目还是Web项目
  2. 查找并加载所有可用初始化器,设置到 initializers 属性中
  3. 找出所有的应用程序监听器,设置到 listeners 属性中
  4. 推断并设置 main 方法的定义类,找到运行的主类

三、 yaml 语法

配置文件

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

  • application.properties
    • 语法结构 : key=value
  • application.yaml
    • 语法结构: key: 空格 value
      配置文件的作用: 修改 SpringBoot 自动配置的默认值,因为 SpringBoot 在底层都给我们自动配置好了。

yaml

YAML 是 “YAML Ain’t a Markup Language”(YAML 不是一种标记语言)的递归缩写。
在开发的这种语言时,YAML 的意思其实是:“Yet Another Markup Language”(仍是一种标记语言)。

标记语言:

  • yaml 配置
server:
    port: 8080
  • xml 配置
<server>
    <port>8080</port>
</server>

yaml 基本语法

YAML 入门教程

  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进不允许使用tab,只允许空格
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • '#'表示注释

1、 对象

# 对象
# 1. 对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格。
student:
  name: 'mianbao'
  age: 3

# 2. 也可以使用 key:{key1: value1, key2: value2, ...}。
student: {name: 'mianbao', age: 3}

2、 数组

# 数组
# 1. 以 - 开头的行表示构成一个数组
pets:
  - cat
  - dog
  - pig

# 2. 可以使用行内表示:key: [value1, value2, ...]
pets: [cat, dog, pig]

3、 纯量

#  纯量
# 纯量是最基本的,不可再分的值,包括:字符串、布尔值、整数、浮点数、Null、时间、日期
boolean:
  - TRUE  #true,True都可以
  - FALSE  #false,False都可以
float:
  - 3.14
  - 6.8523015e+5  #可以使用科学计数法
int:
  - 123
  - 0b1010_0111_0100_1010_1110    #二进制表示
null:
  nodeName: 'node'
  parent: ~  #使用~表示null
string:
  - 哈哈
  - 'Hello world'  #可以使用双引号或者单引号包裹特殊字符
  - newline
    newline2    #字符串可以拆成多行,每一行会被转化成一个空格
date:
  - 2018-02-17    #日期必须使用ISO 8601格式,即yyyy-MM-dd
datetime:
  -  2018-02-17T15:02:31+08:00    #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区

四、给属性赋值的几种方式

yaml 可以直接给实体类赋值
Dog:

@Component
public class Dog {
    private String name;
    private Integer age;
    // getter and setter
}

Person:

@Component
public class Person {
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birth;
    private Map<String, Object> maps;
    private List<Object> lists;
    private Dog dog;
    // getter and setter
}
  • 1. 原来的注解赋值方式:
// 实体类
@Component
public class Dog {
    @Value("旺财")
    private String name;
    @Value("5")
    private Integer age;

    // getter and setter
}

// 测试类
@SpringBootTest
class Springboot02ConfigApplicationTests {

    @Autowired
    private Dog dog;

    @Test
    void contextLoads() {
        System.out.println(dog);
    }
}
  • 2. 使用 yaml:

    application.yaml:

person:
  name: miaobao
  age: 3
  happy: false
  birth: 2020/11/23
  maps: {k1: v1, k2: v2}
  lists:
    - code
    - music
    - girl
  dog:
    name: 旺财
    age: 3

实体类使用注解:@ConfigurationProperties(prefix = “person”)
在这里插入图片描述

解决,引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

@ConfigurationProperties作用:

  • 将配置文件中配置的每一个属性的值,映射到这个组件中;

  • 告诉 springBoot 将本类中的所有属性和配置文件中相关的配置进行绑定

  • 参数 prefix = “person”: 将配置文件中的 person 下面的所有属性—─对应

  • 只有这个组件是容器中的组件,才能使用容器提供的 @ConfigurationProperties 功能

3. 使用 properties 文件

mianbao.properties

name=mianbao

Person 类:

@Component
// 加载指定的配置文件
@PropertySource(value = "classpath:mianbao.properties")
public class Person {

    // 使用 SPEL 取出配置文件的值
    @Value("${name}")
    private String name;
..........
JavaConfig 绑定配置文件的值,可以采取以上方式!

在这里插入图片描述

  • 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下@value
  • 如果说,我们专门编写了一个JavaBean来和配置文件进行映射,就直接使用@configurationProperties!
yaml 配置随机值

它可以生成整数,长整数,uuids或字符串

person:
  name: miaobao${random.uuid}
yaml 的松散绑定

这个什么意思呢?比如我的yml中写的last-name,这个和lastName是一样的,-后面跟着的字母默认是大写的。这就是松散绑定。

dog:
  first-name: 阿黄
  age: 3
@Component
@ConfigurationProperties(prefix = "dog")
public class Dog {
    private String firstName;
    private Integer age;
    ...
}
JSR-303数据校验

这个就是我们可以在字段是增加一层过滤器验证,可以保证数据的合法性复杂类型封装,yml中可以封装对象,使用@value就不支持。

需要带入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

类上面配置 @Validated 注解,需要校验的参数配置上对应的注解,当方法被调用的时候自动对参数校验,如果校验的结果不通过就抛出异常,会打印配置的message的内容。

@Component
@ConfigurationProperties(prefix = "person")
@Validated // 数据校验
public class Person {

    @Email(message = "邮箱格式不正确")
    private String name;
   .....
}

校验规则:
在这里插入图片描述

五、配置文件位置和多环境配置

配置文件位置

SpringBoot版本: 2.4.0

测试时优先级:

  1. 根目录下的:/config/application.yaml
  2. 根目录下的:/application.yaml
  3. classpath: /config/application.yaml
  4. classpath: /application.yaml
server:
  port: 808X # 8081 8082 8083 8084

官方文档的优先级???

  1. The classpath root
  2. The classpath /config package
  3. The current directory
  4. The /config subdirectory in the current directory
  5. Immediate child directories of the /config subdirectory
多环境配置

在这里插入图片描述

application.properties 通过以下配置激活(通过后缀):

# SpringBoot 多环境配置,可以选择激活哪一个配置文件
spring.profiles.active=test

yaml 格式的多环境配置

server:
  port: 8081
spring:
  profiles:
    active: test

# dev 环境
---  # 分隔符
server:
  port: 8082
spring:
  profiles: dev

# test 环境
---
server:
  port: 8083
spring:
  profiles: test

七、 自动配置原理再理解

SpringBoot 配置文件到底能写什么<----联系----> META-INF/spring.factories(自动配置的核心文件)

META-INF/spring.factories 里面的org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration 点进去

// 标注这是一个配置类
@Configuration(proxyBeanMethods = false)

// 自动配置属性 : ServerProperties
@EnableConfigurationProperties(ServerProperties.class)

// ConditionalOnXXX : 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();
	}

	....
}

点进自动配置属性类:ServerProperties, 发现和配置文件里可以配置字段和类 ServerProperties 里属性 相符合。

xxxAutoConfiguration :自动装配从 xxxProperties类 中获取的默认值。
xxxProperties类 和 配置文件 绑定 ,我们就可以使用配置文件进行自定义配置了。

@EnableConfigurationProperties 注解

使用@ConditionalOnProperty注解来控制@Configuration是否生效.
例子:

@Configuration
@ConditionalOnProperty(prefix = "filter",name = "loginFilter",havingValue = "true")
public class FilterConfig {
...
}

配置文件中的代码

filter.loginFilter=true

配置类生效。

@Conditional 注解
  • 标注在类上面,表示该类下面的所有 @Bean 都会启用配置
  • 标注在方法上面,只是对该方法启用配置

@ConditionalOnXXX

自动配置类必须在一定条件下才能生效.
作用:必须是 @ConditionalOn 指定的条件成立,才能给容器中添加组件,配置里面的所有内容才会生效
在这里插入图片描述

这就是自动装配的原理!
 1)、SpringBoot 启动会加载大量的自动配置类
 2)、我们看我们需要的功能有没有在 SpringBoot 默认写好的自动配置类当中;
 3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
 4)、给容器中自动配置类添加组件的时候,会从 properties类 中获取某些属性。我们只需要在配置文件中指定这些属性的值即可;

  • xxxxAutoConfigurartion: 自动配置类: 给容器中添加组件
  • xxxxProperties: 封装配置文件中相关属性

可以通过此配置,来查看哪些自动配置类生效,哪些自动配置类没有生效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值