SpringBoot提供了一种快速使用Spring的方式,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,
全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度上缩短了项目周期。
2014 年 4 月,Spring Boot 1.0.0 发布。Spring的顶级项目之一
官网:https://spring.io/projects/spring-boot
Spring 缺点
虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。一开始,Spring用XML配置,而且是很多XML配置。
Spring 2.5引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显式XML配置。
Spring 3.0引入了基于Java的配置,这是一种类型安全的可重构配置方式,可以代替XML。
所有这些配置都代表了开发时的损耗。因为在思考Spring特性配置和解决业务问题之间需要进行思维切换,所以编写配置挤占了编写应用程序逻辑的时间。和所有框架一样,Spring实用,但它要求的回报也不少。
项目的依赖管理也是一件耗时耗力的事情。
在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。
Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定 Spring配置应该用哪个,不该用哪个。该过程是SpringBoot自动完成的。
起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖 ,这些东西加在一起即支持某项功能。
简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。
Spring Boot 并不是对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方式。
SpringBoot提供了一种快速开发Spring项目的方式,而不是对Spring功能上的增强。
Spring的缺点:
⚫ 配置繁琐
⚫ 依赖繁琐
SpringBoot功能:
⚫ 自动配置
⚫ 起步依赖:依赖传递
⚫ 辅助功能
搭建SpringBoot工程,定义HelloController.hello()方法,返回”Hello SpringBoot!”。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itbluebox</groupId>
<artifactId>springboot-helloworld</artifactId>
<version>1.0-SNAPSHOT</version>
<!--springboot工程需要继承的父工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
</parent>
<dependencies>
<!--web开发的起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
package cn.itbluebox;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //设置当前类是一个Rest风格的Controller
public class HelloController {
@RequestMapping("/hello") //设置当前的方法的映射路径
public String hello(){
return "hello Spring Boot ! 我的第一个SpringBoot项目";
}
}
修改一下当前类所在的包
package cn.itbluebox;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/* 引导类SpringBoot项目的入口 */
@SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class,args);//args有没有都可以
}
}
访问
在日志信息当中可以看到对应的端口号
自动创建好所有的内容
1) spring-boot-starter-parent
<!--springboot工程需要继承的父工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
</parent>
2) spring-boot-starter-web
<dependencies>
<!--web开发的起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
⚫ 在spring-boot-starter-parent中定义了各种技术的版本信息,组合了一套最优搭配的技术版本。
⚫ 在各种starter中,定义了完成该功能需要的坐标合集,其中大部分版本信息来自于父工程。
⚫ 我们的工程继承parent,引入starter后,通过依赖传递,就可以简单方便获得需要的jar包,并且不会存在版本冲突等问题
SpringBoot是基于约定的,所以很多配置都有默认值,
但如果想使用自己的配置替换默认配置的话,就可以使用
application.properties
或者application.yml(application.yaml)
进行配置。
⚫ properties:
server.port=8080
⚫ yml:
server:
port: 8080
server.port=8081
package cn.itbluebox.springbootinit.cn.itbluebox.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //设置当前类是一个Rest风格的Controller
public class HelloController {
@RequestMapping("/hello") //设置当前的方法的映射路径
public String hello(){
return "hello Spring Boot init ! 我的第二个SpringBoot项目";
}
}
运行成功
YAML全称是 YAML Ain’t Markup Language 。
YAML是一种直观的能够被电脑识别的的数据数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持YAML库的不同的编程语言程序导入,比如: C/C++, Ruby, Python, Java, Perl, C/#, PHP
等。
YML文件是以数据为核心的,比传统的xml方式更加简洁。
YAML文件的扩展名可以使用.yml
或者.yaml
。
⚫ properties:
server.port=8080
server.address=127.0.0.1
⚫ xml:
<server>
<port>8080</port>
<address>127.0.0.1</address>
</server>
⚫ yml:
server:
port: 8080
address: 127.0.0.1
简洁,以数据为核心
⚫ 大小写敏感
⚫ 数据值前边必须有空格,作为分隔符
⚫ 使用缩进表示层级关系
⚫ 缩进时不允许使用Tab键,只允许使用空格(各个系统 Tab对应的 空格数目可能不同,导致层次混乱)。
⚫ 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
⚫ /# 表示注释,从这个字符一直到行尾,都会被解析器忽略。
server:
port: 8080
address: 127.0.0.1
name: abc
⚫ 对象(map):键值对的集合。 注意冒号后的空格
person:
name: zhangsan
#行内写法
person: {name: zhangsan}
⚫ 数组:一组按次序排列的值
address:
- beijing
- shanghai
#行内写法
address: [beijing,shanghai]
⚫ 纯量:单个的、不可再分的值
msg1: 'hello \n world' # 单引忽略转义字符
msg2: "hello \n world" # 双引识别转义字符
⚫ YAML:参数引用
name: lisi
person:
name: ${name} # 引用上边定义的name值
创建application.yml
server:
port: 8082
创建application.yaml
server:
port: 8083
将application.yml当中的内容注释掉
将三个配置文件当中的配置都打开
重新运行
上述证明application.properties的优先顺序高于application.yaml和application.yml
运行测试
证明application.yml 要高于application.yaml优先级别
优先级:application.properties高于application.yml 要高于application.yaml
server:
port: 8082
name: abc
# 对象
person:
name: 张三
age: 20
# 对象行内写法
person2: {name: 李四, age : 30}
# 数组
address:
- beijing
- shanghai
# 纯量
msg1: 'hello \n world' #不会识别转义字符,会原样输出
msg2: "hello \n world" #会识别转义字符,输出换行
@Value
读取对应的值package cn.itbluebox.springbootinit.cn.itbluebox.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //设置当前类是一个Rest风格的Controller
public class HelloController {
@Value("${name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name;
@RequestMapping("/hello2") //设置当前的方法的映射路径
public String hello2(){
System.out.println(name);
return "hello Spring Boot init ! 我的第二个SpringBoot项目 name的值为:"+name;
}
@RequestMapping("/hello") //设置当前的方法的映射路径
public String hello(){
return "hello Spring Boot init ! 我的第二个SpringBoot项目";
}
}
运行测试
package cn.itbluebox.springbootinit.cn.itbluebox.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //设置当前类是一个Rest风格的Controller
public class HelloController {
@Value("${name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name;
@Value("${person.name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name2;
@Value("${person.age}")//${}当中的内容必须和配置文件当中的键的值所对应
private int age;
@RequestMapping("/hello2") //设置当前的方法的映射路径
public String hello2(){
System.out.println(name);
System.out.println(name2);
System.out.println(age);
return "hello Spring Boot init ! 我的第二个SpringBoot项目 name的值为:"+name +" name2:"+name2+" age:"+age;
}
@RequestMapping("/hello") //设置当前的方法的映射路径
public String hello(){
return "hello Spring Boot init ! 我的第二个SpringBoot项目";
}
}
重新运行并测试
-参数注入
修改application.yml
server:
port: 8082
name: abc
# 对象
person:
name: ${name}
age: 20
# 对象行内写法
person2: {name: 李四, age : 30}
# 数组
address:
- beijing
- shanghai
# 纯量
msg1: 'hello \n world' #不会识别转义字符,会原样输出
msg2: "hello \n world" #会识别转义字符,输出换行
重新运行并测试
package cn.itbluebox.springbootinit.cn.itbluebox.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //设置当前类是一个Rest风格的Controller
public class HelloController {
@Value("${name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name;
@Value("${person.name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name2;
@Value("${person.age}")//${}当中的内容必须和配置文件当中的键的值所对应
private int age;
@Value("${address[0]}")//${}当中的内容必须和配置文件当中的键的值所对应
private String address;
@RequestMapping("/hello2") //设置当前的方法的映射路径
public String hello2(){
System.out.println(name);
System.out.println(name2);
System.out.println(age);
System.out.println(address);
return "hello Spring Boot init ! 我的第二个SpringBoot项目 name的值为:"
+name +" name2:"+name2+" age:"+age
+" address:"+address
;
}
@RequestMapping("/hello") //设置当前的方法的映射路径
public String hello(){
return "hello Spring Boot init ! 我的第二个SpringBoot项目";
}
}
重新运行并测试
package cn.itbluebox.springbootinit.cn.itbluebox.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //设置当前类是一个Rest风格的Controller
public class HelloController {
@Value("${name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name;
@Value("${person.name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name2;
@Value("${person.age}")//${}当中的内容必须和配置文件当中的键的值所对应
private int age;
@Value("${address[0]}")//${}当中的内容必须和配置文件当中的键的值所对应
private String address;
@Value("${msg1}")//${}当中的内容必须和配置文件当中的键的值所对应
private String msg1;
@Value("${msg2}")//${}当中的内容必须和配置文件当中的键的值所对应
private String msg2;
@RequestMapping("/hello2") //设置当前的方法的映射路径
public String hello2(){
System.out.println(name);
System.out.println(name2);
System.out.println(age);
System.out.println(address);
System.out.println(msg1);
System.out.println(msg2);
return "hello Spring Boot init ! 我的第二个SpringBoot项目 name的值为:"
+name +" name2:"+name2+" age:"+age
+" address:"+address
+" msg1:"+msg1
+" msg2:"+msg2;
}
@RequestMapping("/hello") //设置当前的方法的映射路径
public String hello(){
return "hello Spring Boot init ! 我的第二个SpringBoot项目";
}
}
重新运行并测试
获取对应的值
package cn.itbluebox.springbootinit.cn.itbluebox.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //设置当前类是一个Rest风格的Controller
public class HelloController {
@Value("${name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name;
@Value("${person.name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name2;
@Value("${person.age}")//${}当中的内容必须和配置文件当中的键的值所对应
private int age;
@Value("${address[0]}")//${}当中的内容必须和配置文件当中的键的值所对应
private String address;
@Value("${msg1}")//${}当中的内容必须和配置文件当中的键的值所对应
private String msg1;
@Value("${msg2}")//${}当中的内容必须和配置文件当中的键的值所对应
private String msg2;
@Autowired
private Environment env;//SpringBoot启动的时候会在Spring容器当中初始化Environment对象
@RequestMapping("/hello2") //设置当前的方法的映射路径
public String hello2(){
System.out.println(name);
System.out.println(name2);
System.out.println(age);
System.out.println(address);
System.out.println(msg1);
System.out.println(msg2);
System.out.println("-----------------");
System.out.println(env.getProperty("name"));
System.out.println(env.getProperty("person.name"));
System.out.println(env.getProperty("person.age"));
System.out.println(env.getProperty("address[0]"));
System.out.println(env.getProperty("msg1"));
System.out.println(env.getProperty("msg2"));
return "hello Spring Boot init ! 我的第二个SpringBoot项目 name的值为:"
+name +" name2:"+name2+" age:"+age
+" address:"+address
+" msg1:"+msg1
+" msg2:"+msg2
+" <br>env.getProperty(\"name)="+env.getProperty("name")
+" env.getProperty(\"person.name\")="+env.getProperty("person.name")
+" env.getProperty(\"person.age\")="+env.getProperty("person.age")
+" env.getProperty(\"address[0]\")="+env.getProperty("address[0]")
+" env.getProperty(\"msg1\")="+env.getProperty("msg1")
+" env.getProperty(\"msg2\")="+env.getProperty("msg2")
;
}
@RequestMapping("/hello") //设置当前的方法的映射路径
public String hello(){
return "hello Spring Boot init ! 我的第二个SpringBoot项目";
}
}
运行测试
重新运行并测试
package cn.itbluebox.springbootinit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component //将Person 容器当中
@ConfigurationProperties
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package cn.itbluebox.springbootinit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //设置当前类是一个Rest风格的Controller
public class HelloController {
@Value("${name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name;
@Value("${person.name}")//${}当中的内容必须和配置文件当中的键的值所对应
private String name2;
@Value("${person.age}")//${}当中的内容必须和配置文件当中的键的值所对应
private int age;
@Value("${address[0]}")//${}当中的内容必须和配置文件当中的键的值所对应
private String address;
@Value("${msg1}")//${}当中的内容必须和配置文件当中的键的值所对应
private String msg1;
@Value("${msg2}")//${}当中的内容必须和配置文件当中的键的值所对应
private String msg2;
@Autowired
private Environment env;//SpringBoot启动的时候会在Spring容器当中初始化Environment对象
@Autowired
private Person person;
@RequestMapping("/hello2") //设置当前的方法的映射路径
public String hello2(){
System.out.println(name);
System.out.println(name2);
System.out.println(age);
System.out.println(address);
System.out.println(msg1);
System.out.println(msg2);
System.out.println("-----------------");
System.out.println(env.getProperty("name"));
System.out.println(env.getProperty("person.name"));
System.out.println(env.getProperty("person.age"));
System.out.println(env.getProperty("address[0]"));
System.out.println(env.getProperty("msg1"));
System.out.println(env.getProperty("msg2"));
System.out.println("------------------");
System.out.println("person"+person);
return "hello Spring Boot init ! 我的第二个SpringBoot项目 name的值为:"
+name +" name2:"+name2+" age:"+age
+" address:"+address
+" msg1:"+msg1
+" msg2:"+msg2
+" <br>env.getProperty(\"name)="+env.getProperty("name")
+" env.getProperty(\"person.name\")="+env.getProperty("person.name")
+" env.getProperty(\"person.age\")="+env.getProperty("person.age")
+" env.getProperty(\"address[0]\")="+env.getProperty("address[0]")
+" env.getProperty(\"msg1\")="+env.getProperty("msg1")
+" env.getProperty(\"msg2\")="+env.getProperty("msg2")
+" person = "+person
;
}
@RequestMapping("/hello") //设置当前的方法的映射路径
public String hello(){
return "hello Spring Boot init ! 我的第二个SpringBoot项目";
}
}
运行测试
重新运行并测试
@Component //将Person 容器当中
@ConfigurationProperties
public class Person {
上面默认读取的是
@ConfigurationProperties(prefix = "person")
运行测试
重新运行并测试
http://localhost:8082/hello2
得到Person对应的值
得到对应配置文件的值
# 对象
person:
name: ${name}
age: 20
address:
- beijing
- shanghai
package cn.itbluebox.springbootinit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component //将Person 容器当中
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private int age;
private String[] address;
public Person() {
}
public Person(String name, int age, String[] address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String[] getAddress() {
return address;
}
public void setAddress(String[] address) {
this.address = address;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address=" + Arrays.toString(address) +
'}';
}
}
运行测试
重新运行并测试
点击后跳转到网页提示(添加如下的配置依赖)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
点击
Person显示正常
同时在application.yml编写配置的时候会有一些提示信息
先删除其他的配置文件
编辑application.yml的时候会有提示
我们在开发Spring Boot应用时,通常同一套程序会被安装到不同环境,比如:开发、测试、生产等。其中数据库地址、服务器端口等等配置都不同,如果每次打包时,都要修改配置文件,那么非常麻烦。profile功能就是来进行动态配置切换的
创建几个文件
server.port=8081
server.port=8082
server.port=8083
默认端口号为8080,而且没有激活配置文件
spring.profiles.active的值需要和对应配置文件-后面从名称相符
spring.profiles.active=dev
上述配置激活了application-dev.properties
重新运行启动
成功激活application-dev.properties配置文件对应的内容
-生产的时候激活pro
spring.profiles.active=pro
激活成功
---
server:
port: 8081
spring:
profiles: dev
---
server:
port: 8082
spring:
profiles: test
---
server:
port: 8083
spring:
profiles: pro
---
直接重新运行
默认端口号为8080,没有激活配置文件
---
server:
port: 8081
spring:
profiles: dev
---
server:
port: 8082
spring:
profiles: test
---
server:
port: 8083
spring:
profiles: pro
---
spring:
profiles:
active: pro
开启了8083端口,证明
---
server:
port: 8083
spring:
profiles: pro
---
配置生效,其他的配置也一样
配置成功,虚拟机配置覆盖了配置文件的配置
命令行参数配置成功
打包成功
在cmd当中进入对应的目录当中
java -jar springboot-profiles-0.0.1-SNAPSHOT.jar
运行成功使用的pro环境,端口号为8083
Ctrl+c停止运行
java -jar springboot-profiles-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
变成了dev环境,端口号为8081
Springboot程序启动时,会从以下位置加载配置文件:
file:/config/
:当前项目下的/config目录下file:./
︰当前项目的根目录classpath:/config/
: classpath的/config目录classpath:/
: classpath的根目录加载顺序为上文的排列顺序,高优先级配置的属性会生效
classpath:/
: classpath的根目录)server.port=8081
classpath:/config/
: classpath的/config目录)将application.properties复制到config目录当中
server.port=8082
端口变为8082
package cn.itbluebox.springbootconfig;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "你好";
}
}
打包成功
打包后的路径,进入对应的目录打开cmd
java -jar springboot-config-0.0.1-SNAPSHOT.jar --server.port=8082 --server.servlet.context-path=/hehe
http://localhost:8082/hehe/hello
在电脑随便的地方创建配置文件
java -jar springboot-config-0.0.1-SNAPSHOT.jar --spring.config.location=e://1/application.properties
端口号变为配置文件当中的8085
在target当中创建配置文件
java -jar springboot-config-0.0.1-SNAPSHOT.jar
在target下创建config目录,将配置文件创建到config目录下
java -jar springboot-config-0.0.1-SNAPSHOT.jar
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_44757034/article/details/120922096
内容来源于网络,如有侵权,请联系作者删除!