文章目录
一、简介
1.1、Spring
Spring是一个为了解决企业级应用开发的复杂性而创建的简化开发的轻量级框架
Spring简化开发的方式:
- 基于POJO的轻量级和最小入侵编程,所有的东西都是bean
- 通过IOC,依赖注入(DI)和面向接口实现松耦合
- 基于切面(AOP)和惯例进行声明式编程
- 通过切面和模板减少样式代码,如RedisTemplate等
1.2、SpringBoot
SpringBoot是一个javaweb的开发框架,和SpringMVC类似。和其他的javaweb框架相比,可以简化开发,约定大于配置。
随着Spring的发展,项目开发时需要整合越来越多的文件,逐渐变成了配置地狱。由此SpringBoot开发框架被抽象出来了,目的是为了让开发人员更容易使用Spring,更容易集成各种常用的中间件和开源软件。
SpringBoot基于Spring开发,但SpringBoot本身并不提供Spring的核心特新及扩展功能。也就是说,SpringBoot并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。SpringBoot以约定大于配置的思想,默认进行了很多设置,多数SpringBoot应用只需要很少的Spring配置。同时,它也集成了大量常用的第三方配置库(如:Redis,RabbitMQ,Quartz等),SpringBoot应用中这些第三方库几乎可以零配置的开箱即用。
简单来说,SpringBoot其实不是新的框架,它只是默认配置了很多框架的使用方式,像Maven整合jar包一样整合了所有的框架。
SpringBoot的主要优点:
- 开箱即用,提供各种默认配置来简化项目配置
- 内嵌式容器简化web项目
- 没有冗余代码生成和XML配置的要求
二、HelloWorld
2.1、创建基础项目说明
使用IDEA直接创建项目
- 创建一个新项目
- 选择spring initalizr,可以看到默认就是去官网的快速构建工具那里实现
- 填写项目信息
- 选择初始化的组件(勾选web即可)
- 填写项目路径
- 等待项目构建成功
项目结构分析
通过上面的步骤完成基础项目的构建,就会生成以下文件:
- 程序的启动类
- 一个 application.properties 配置文件
- 一个测试类
- 一个pom.xml
2.2、pom.xml分析
<!-- 父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<!-- web场景启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springboot单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<!-- 剔除依赖 -->
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 打包插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.3、编写HTTP接口
-
在主程序(启动类)的同级目录下,新建一个controller包。其他目录下识别不到
-
新建一个HelloController类
@RestController public class HelloController { @RequestMapping("/hello") public String hello() { return "Hello World"; } }
-
从主程序启动项目,浏览器发起请求,查看页面返回
2.4、将项目打成jar包
点击Maven的package
如果遇到以上错误,可以配置打包时 跳过项目运行测试用例
<!--
在工作中,很多情况下我们打包是不想执行测试用例的
可能是测试用例不完事,或是测试用例会影响数据库数据
跳过测试用例执
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--跳过项目运行测试用例-->
<skipTests>true</skipTests>
</configuration>
</plugin>
如果打包成功,在target文件下会生成一个jar包
打完包以后就可以在任何地方运行了。
运行命令:java -jar xxx.jar
2.5、修改启动时控制器的字母
在项目的resource目录下新建一个banner.txt。
在banner生成器网站生成字符,然后拷贝到banner.txt中即可
三、Yaml语法
3.1、配置文件
SpringBoot使用一个全局的配置文件,配置文件名称是固定的
- application.properties
- 语法结构 : key=value
- application.yml
- 语法结构 :key:空格 value
配置文件的作用: 修改SpringBoot自动配置的默认值,因为SpringBoot在底层都自动配置好了
比如在配置文件中修改Tomcat默认启动的端口号
server.port=8081
3.2、Yaml概述
YAML这种语言以数据作为中心,而不是以标记语言为重点。
以前的配置文件大多使用xml来配置,比如端口配置:
xml配置:
<server>
<port>8081</port>
</server>
yaml配置:
server:
port: 8082
3.3、yml基础语法
yml语法要求严格:
- 空格不能省略
- 以缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的
- 属性和值的大小写是十分敏感的
字面量: 普通的值[数字,布尔值,字符串]
字面量直接写在后面就可以,字符串默认不用加上双引号或者单引号
k: v
注意:
- 双引号不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思
比如:name: “hello \n world” 输出 : hello 换行 world - 单引号会转义特殊字符,特殊字符最终会变成和普通字符一样输出
比如 : name: ‘hello \n world’ 输出 : hello \n world
对象、Map(键值对)
# 对象、Map格式
K:
v1:
v2:
在下一行来写对象属性和值的关系,注意缩进,比如:
student:
name: xiaoming
age: 3
行内写法
student: {name: xiaoming,age: 3}
数组(List、Set)
用-
表示数组中的一个元素,比如:
pets:
- cat
- dog
- pig
行内写法
pets: [cat,dog,pig]
修改SpringBoot的默认端口号
配置文件中添加端口号的参数,就可以切换端口:
server:
port: 8082
四、注入配置文件
yaml文件更强大的地方在于它可以给实体类直接注入匹配值
4.1、Yaml注入配置文件
-
在SpringBoot项目中的resources目录下新建一个application.yml
-
实体类Dog
@Component // 注册bean到容器中 public class Dog() { private String name; private Integer age; // 构造器、getter/setter、toString }
-
通过@Value给bean注入属性值
@Component // 注册bean到容器中 public class Dog() { @Value("汪汪") private String name; @Value("8") private Integer age; }
-
在SpringBoot的测试类下输出Dog
@SpringBootTest class DemoApplicationTests { @Autowired //将对象自动注入进来 Dog dog; @Test public void contextLoads() { System.out.println(dog); //打印对象 } }
-
再写一个复杂一点的Person类
@Component //注册bean到容器中 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; //有参无参构造、get、set方法、toString()方法 }
-
使用yaml配置的方式进行注入
person: name: xiaoming age: 3 happy: false birth: 2000/01/01 maps: {k1: v1,k2: v2} lists: - code - game - music dog: name: 汪汪 age: 1
-
把person这个对象的值注入到类中
/* @ConfigurationProperties作用: 将配置文件中配置的每一个属性的值,映射到这个组件中; 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定 参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应 */ @Component //注册bean @ConfigurationProperties(prefix = "person") 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; }
-
导入配置文件处理器,配置文件进行绑定就会有提示
<!-- 导入配置文件处理器,配置文件进行绑定就会有提示,需要重启 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
-
在测试类中测试
@SpringBootTest class DemoApplicationTests { @Autowired Person person; //将person自动注入进来 @Test public void contextLoads() { System.out.println(person); //打印person信息 } }
将配置文件的key 值 和 属性的值设置为不一样,则结果输出为null,注入失败
4.2、加载指定配置文件
- @PropertySource:加载指定的配置文件
- @ConfigurationProperties:默认从全局配置文件中获取值
-
在resources目录下新建一个person.properties文件
name=xiaoming
-
在代码中指定加载person.properties文件
@PropertySource(value = "classpath:person.properties") @Component //注册bean public class Person { @Value("${name}") private String name; }
-
测试输出
4.3、配置文件占位符
person:
name: xiaoming${random.uuid} # 随机uuid
age: ${random.int} #随机int
happy: false
birth: 2000/01/01
maps: {k1: v1,k2: v2}
lists:
- code
- girl
- music
dog:
# 引用person.hello的值,如果不存在就用 : 后面的值,即other,然后拼接上_汪汪
name: ${person.hello:other}_汪汪
age: 1
4.4、回顾properties配置
注意: properties配置文件在写中文的时候会有乱码,需要在setting --> FileEncodings
中配置
步骤:
-
新建一个User实体类
@Component //注册bean public class User { private String name; private int age; private String sex; }
-
编辑配置文件 user.properties
user.name=user user.age=18 user.sex=男
-
在User类上使用@Value来进行注入
@Component //注册bean @PropertySource(value = "classpath:user.properties") public class User { //直接使用@value @Value("${user.name}") //从配置文件中取值 private String name; @Value("#{9*2}") // #{SPEL} Spring表达式 private int age; @Value("男") // 字面量 private String sex; }
-
测试输出
4.5、对比
- @ConfigurationProperties只需要写一次,@Value需要每个字段都添加
- 松散绑定:比如yaml中写的是last-name,这个和lastName是一样的,
-
后面跟的字母默认大写 - JSR303数据校验:在字段增加一层过滤验证,保证数据的合法性
- 复杂类型封装:yml中可以封装对象,value不支持
4.6、JSR303数据校验
SpringBoot中可以用@Validated来校验数据,如果数据异常会统一抛出异常,方便异常中心统一处理。
@Component //注册bean
@ConfigurationProperties(prefix = "person")
@Validated //数据校验
public class Person {
@Email(message="邮箱格式错误") //name必须是邮箱格式
private String name;
@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;
}
五、多环境切换
profile是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境。
5.1、多配置文件
在主配置文件编写的时候,文件名可以是application-{profile}.properties/yml , 用来指定多个环境版本
例如:application-test.properties 代表测试环境配置 application-dev.properties 代表开发环境配置
但是Springboot并不会直接启动这些配置文件,它默认使用application.properties主配置文件
需要通过一个配置来选择需要激活的环境:
#比如在配置文件中指定使用dev环境,我们可以通过设置不同的端口号进行测试;
#我们启动SpringBoot,就可以看到已经切换到dev下的配置了;
spring.profiles.active=dev
5.2、yml的多文档块
和properties配置文件中一样,但是使用yml去实现不需要创建多个配置文件
server:
port: 8081
#选择要激活那个环境块
spring:
profiles:
active: prod
---
server:
port: 8083
spring:
profiles: dev #配置环境的名称
---
server:
port: 8084
spring:
profiles: prod #配置环境的名称
注意:如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配
置文件
5.3、配置文件加载位置
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
优先级1:项目路径下的config文件夹配置文件
优先级2:项目路径下配置文件
优先级3:资源路径下的config文件夹配置文件
优先级4:资源路径下配置文件
优先级由高到底,高优先级的配置会覆盖低优先级的配置
SpringBoot会从这四个位置全部加载主配置文件,互补配置
在最低级的配置文件中设置一个项目访问路径的配置来测试互补问题
#配置项目的访问路径
server.servlet.context-path=/server
扩展:指定位置加载配置文件
通过spring.config.location可以改变默认的配置文件位置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;相同配置,外部指定的配置文件优先级最高
java -jar spring-boot-config.jar --spring.config.location=F:/application.properties