本章将介绍使用 IDEA 工具如何快速构建 SpringBoot 项目,以及 SpringBoot 项目的起步依赖原理分析,SpringBoot 的配置以及配置的加载顺序。
SpringBoot 提供了一种快速使用 Spring 的方式,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度上缩短了项目周期。2014年4月,Spring Boot 1.0.0 发布。Spring 的顶级项目之一( https://spring.io )。
- 配置繁琐
虽然 Spring 的组件代码是轻量级的,但它的配置却是重量级的。一开始, Spring 用 XML 配置,而且是很多 XML 配置。Spring 2.5 引入了基于注解的组件扫描,这消除了大量针对应用程序自身组件的显式 XML 配置。Spring 3.0 引入了基于 Java 的配置,这是一种类型安全的可重构配置方式,可以代替 XML 。所有这些配置都代表了开发时的损耗。因为在思考 Spring 特性配置和解决业务问题之间需要进行思维切换,所以编写配置挤占了编写应用程序逻辑的时间。和所有框架一样,Spring 实用,但它要求的回报也不少。- 依赖繁琐
项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。
1)自动配置
Spring Boot 的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定 Spring 配置应该用哪个,不该用哪个。该过程是 SpringBoot 自动完成的。
2)起步依赖
起步依赖本质上是一个 Maven 项目对象模型( Project Object Model,POM ),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
3)辅助功能
提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。
Spring Boot并不是对 Spring 功能上的增强,而是提供了一种快速使用Spring 的方式。
本操作需要网络环境良好,否则无法快速搭建。
菜单选择 File -> New -> Project,选择 Spring Initializr。
点击 Next 进入下一步,选择语言以及项目打包方式,并且指定 Java 版本。
点击 Next 进入本页面,可以选择项目需要的依赖,这里我选择了 Spring Web 的依赖以及 LomBok 的依赖。
点击 Next 进入本页面,填写项目名称,点击 Finish 创建项目。
项目创建成功后,点击 File -> Settings,如图配置项目的 Maven 信息。
创建测试类,启动并访问项目。
package com.springboot.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello SpringBoot!";
}
}
SpringBoot 的引导类,是项目入口,运行 main 方法就可以启动项目(Controller 需要放在引导类同级或者子级目录下,否则启动访问会404)。
启动项目,浏览器访问接口,成功返回 ‘Hello SpringBoot!’ 。
使用 Spring 和 SpringBoot 构建的项目,业务代码编写方式完全一样。
打开项目的 pom.xml 文件,可以看到自动引入了 spring-boot-starter-parent 以及 spring-boot-starter-web 两个坐标。
1)spring-boot-starter-parent
本坐标是项目依赖的父工程,点进去可以发现它又依赖于 2.6.1 版本的 org.springframework.boot 父工程。
进入这个坐标可以发现 标签中定义了很多常用技术的版本信息,这些都是 spring-boot-starter-parent 整合好的,组合了一套最优的技术版本,我们不需要自行再去选择版本,这样的好处就是不会存在版本冲突的问题。
2)spring-boot-starter-web
因为我已经依赖于 spring-boot-starter-parent 父工程,在父工程中,已经通过版本锁定,定义好了 spring-boot-start-web 的版本信息,所以在这里不需要指定版本.
点击进入 start-web 可以发现这个坐标依赖的一些坐标信息,此处没有版本锁定。
可以看到其中依赖了 spring-web 以及 spring-webmvc 两个坐标信息,通过依赖传递的特性,本项目也就依赖了 spring-boot-starter-web 中的坐标。
小结:
1.spring-boot-starter-parent 中定义了各种技术的版本信息,组合了一套最优搭配的技术版本。
2.在各种 starter 中,定义了完成该功能需要的坐标合集,其中大部分版本信息来自于父工程。
3.我们的工程继承 parent 的 jar 包,并且不会存在版本冲突等问题。引入 starter 后,通过依赖传递,就可以简单方便获得需要的依赖
SpringBoot 是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用 application.properties 或者 application.yml / application.yaml 进行配置。
server.port=8080
server:
port: 8080
SpringBoot提供了2种配置文件类型:properties 和 yml/yaml
默认的配置文件名称为:application
在同一目录下配置文件的优先级为:properties > yml > yaml
YAML 全称是 YAML Ain’t Markup Language 。YAML 是一种直观的能够被电脑识别的的数据数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持 YAML 库的不同的编程语言程序导入,比如: C/C+ + , Ruby, Python, Java, Perl, C#, PHP 等。YML 文件是以数据为核心的,比传统的 xml 方式更加简洁。
YAML 文件的扩展名可以使用 .yml 或者 .yaml 。
server.port=8080
server.address=127.0.0.1
>
>8080 >
>127.0.0.1>
>
server:
port: 8080
address: 127.0.0.1
yaml 的特点是简洁,以数据为核心。
person:
name: xinghe
# 行内写法
person: {name: xinghe}
address:
- beijing
- guangzhou
# 行内写法
address: [beijing,guangzhou]
数组使用 “-” 表示数组每个元素
# 单引忽略转义字符
msg1: 'hello \n xinghe'
# 双引识别转义字符
msg2: "hello \n xinghe"
name: xinghe
person:
# 引用上面定义的name值
name: ${name}
package com.springboot.demo;
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
public class HelloController {
@Value("${name}")
private String name;
@Value("${person.name}")
private String personName;
@Value("${address[0]}")
private String[] address1;
@RequestMapping("/hello")
public String hello() {
System.out.println(name);
System.out.println(personName);
System.out.println(address1);
return "Hello SpringBoot!";
}
}
package com.springboot.demo;
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
public class HelloController {
@Value("${name}")
private String name;
@Value("${person.name}")
private String personName;
@Value("${address[0]}")
private String[] address1;
@Autowired
private Environment environment;
@RequestMapping("/hello")
public String hello() {
System.out.println(name);
System.out.println(personName);
System.out.println(address1);
System.out.println("-----------------------------------");
System.out.println(environment.getProperty("person.name"));
System.out.println(environment.getProperty("address[0]"));
return "Hello SpringBoot!";
}
}
@Data
本注解会自动生成get和set以及其他的一些方法,这里不多做解释。
@component
是spring中的一个注解,它的作用就是实现bean的注入。
@ConfigurationProperties
Spring源码中大量使用了ConfigurationProperties注解,比如server.port就是由该注解获取到的,通过与其他注解配合使用,能够实现Bean的按需配置。
该注解有一个prefix属性,通过指定的前缀,绑定配置文件中的配置,该注解可以放在类上,也可以放在方法上。
package com.springboot.demo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private String age;
}
使用 @ConfigurationProperties 注解 IDEA 会提示 “Spring Boot Configuration Annotation Processor not configured” 。
在 pom.xml 文件中添加一个依赖就可以解决。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
在 Controller 中注入 Person 对象就可以使用其读取的配置文件的值。
package com.springboot.demo;
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
public class HelloController {
@Value("${name}")
private String name;
@Value("${person.name}")
private String personName;
@Value("${address[0]}")
private String[] address1;
@Autowired
private Environment environment;
@Autowired
private Person person;
@RequestMapping("/hello")
public String hello() {
System.out.println(name);
System.out.println(personName);
System.out.println(address1);
System.out.println("-----------------------------------");
System.out.println(environment.getProperty("person.name"));
System.out.println(environment.getProperty("address[0]"));
System.out.println("-----------------------------------");
System.out.println(person.getName());
System.out.println(person.getAge());
return "Hello SpringBoot!";
}
}
在开发 SpringBoot 应用时,通常同一套程序会被安装到不同环境,比如:开发、测试、生产等。其中数据库地址服务器端口等等配置都不同,如果每次打包时,都要修改配置文件,那么非常麻烦。 profile 功能就是来进行动态配置切换的。
可以提供多个配置文件,每一个代表一种环境。
application-dev.properties/yml 开发环境
application-test.properties/yml 测试环境
application-pro.properties/yml 生产环境
通过在 application.properties/yml 中编写如下代码指定某个配置文件实现各个环境的切换激活。
spring:
profiles:
active: dev
在 yml 文件中通过 “—” 分隔不同的配置。
通过 spring.profiles 来指定不同的配置名称,同样以 spring.profiles.active 来指定激活哪个配置。
---
server:
port: 8081
spring:
profiles: dev
---
server:
port: 8082
spring:
profiles: test
---
server:
port: 8083
spring:
profiles: pro
---
spring:
profiles:
active: test
在配置文件中配置:spring.profiles.active=dev ,同上
在 VM options 指定:-Dspringprofiles.active=dev
在 Program arguments 指定:–springprofiles.active=dev
通过打 jar 包的方式在 jar 包根目录打开命令行运行 java -jar xxx.jar --spring.profiles.active=dev 命令也可以指定激活配置文件。
Springboot 程序启动时,会从以下位置加载配置文件:
- file:./config/:当前项目下的 /config 目录下
- file:./ :当前项目的根目录
- classpath:/canfig/:classpath的 /config 目录
- classpath:/ :classpath 的根目录加载顺序为上文的排列顺序,高优先级配置的属性会生效
如果在不同的位置中有多个文件,那么多个文件都会加载,会形成一种互补的配置。
可以通过官网查看外部属性加载顺序
进入官网后找到外部化配置菜单,从低到高依次排序:
继续向下寻找可以看到,可以通过命令可以直接指定激活外部的配置文件:
比如我有一个配置文件在E盘的根目录下,那么我就可以在运行启动命令的后面加上 “–spring.config.location=e://application.properties” 指定激活我的配置文件。
也可以把配置文件放在 jar 包所在的 target 根目录下,跟jar包同级的情况下直接运行jar包,就可以自动激活配置文件,还可以在 target 目录下 创建 config 文件夹,在文件夹中放入配置文件,启动时同样也会自动激活。
由此可以看出外部配置和内部配置形成了一种互补的关系。
例如:
当项目打包完毕后,我突然发现有一些配置忘记调整过来,或者没有指定到生产环境的配置,那么现在就有两种解决方案:
1.修改项目配置文件后重新打包。
2.使用外部配置,把少量需要修改的配置放在外部配置文件中,因为外部配置的优先级较高,所以项目启动时就会覆盖掉项目内相应的配置信息。
今天就分享到这里,后续我还会继续发布一些自己的学习内容,希望可以跟大家共同进步。