2.4 多环境配置
新建项目springboot_04_profile
Group:com.itheima
Artifact:springboot_04_profile
创建控制层
以后在工作中,对于开发环境、测试环境、生产环境的配置肯定都不相同,比如我们开发阶段会在自己的电脑上安装 mysql,连接自己电脑上的 mysql 即可,但是项目开发完毕后要上线就需要该配置,将环境的配置改为线上环境的。
来回的修改配置会很麻烦,而 SpringBoot 给开发者提供了多环境的快捷配置,需要切换环境时只需要改一个配置即可。不同类型的配置文件多环境开发的配置都不相同,接下来对不同类型的配置文件进行说明。
2.4.1 yaml文件
在 application.yml 中使用 — 来分割不同的配置,内容如下
application.yml
#开发环境
server:
port: 9000
spring:
profiles: dev
---
#生产环境
server:
port: 9001
spring:
profiles: pro
---
#测试环境
server:
port: 9002
spring:
profiles: test
上面配置中 spring.profiles 是用来给不同的配置起名字的。而如何告知 SpringBoot 使用哪段配置呢?可以使用如下配置来启用都一段配置。
application.yml
#设置启用的环境
spring:
profiles:
active: dev #表示使用的是开发环境
综上所述, application.yml 配置文件内容如下
#设置启用的环境
spring:
profiles:
active: dev #表示使用的是开发环境
---
#开发环境
server:
port: 9000
spring:
profiles: dev
---
#生产环境
server:
port: 9001
spring:
profiles: pro
---
#测试环境
server:
port: 9002
spring:
profiles: test
重新启动,看一下控制台启动的端口号,是开发的
注意:
在上面配置中给不同配置起名字的 spring.profiles 配置项已经过时。最新用来起名字的配置项是:
application.yml
application.yml代码如下:
#开发环境
spring:
config:
activate:
on-profile: dev
server:
port: 9000
我们再重启一下,一样是开发库的端口
2.4.2 properties文件
properties 类型的配置文件配置多环境需要定义不同的配置文件。
在application.properties中配置
#设置启动的环境
spring.profiles.active=dev
- 新建application-dev.properties,它是开发环境的配置文件。我们在该文件中配置端口号为 7000
server.port=7000
- application-test.properties 是测试环境的配置文件。我们在该文件中配置端口号为 7001
server.port=7001
- application-pro.properties 是生产环境的配置文件。我们在该文件中配置端口号为 7002
server.port=7002
配置文件如下
SpringBoot 只会默认加载名为 application.properties 的配置文件(优先级高),启动应用
这时候我们把application.properties修改一下
#设置启动的环境
spring.profiles.active=pro
再启动一下
2.4.3 命令行启动参数设置
把几个文件拖到bak中
设置文件的编码,更改成UTF-8
执行clean然后再package
使用 SpringBoot 开发的程序以后都是打成 jar 包,通过 java -jar xxx.jar 的方式启动服务的。那么就存在一个问题,如何切换环境呢?因为配置文件打到的jar包中了。
我们知道 jar 包其实就是一个压缩包,可以解压缩,然后修改配置,最后再打成jar包就可以了。这种方式显然有点麻烦,而 SpringBoot 提供了在运行 jar 时设置开启指定的环境的方式,如下
java -jar springboot_04_profile-0.0.1-SNAPSHOT.jar
打包完,看一下端口9000
和配置的application.yml中配置的一样
切换测试端口
指令如下
java -jar springboot_04_profile-0.0.1-SNAPSHOT.jar --spring.profiles.active=test
那么这种方式能不能临时修改端口号呢?也是可以的,可以通过如下方式
java -jar springboot_04_profile-0.0.1-SNAPSHOT.jar --server.port=8888
输入后,端口更改
当然也可以同时设置多个配置,比如即指定启用哪个环境配置,又临时指定端口,如下:
java -jar springboot_04_profile-0.0.1-SNAPSHOT.jar --spring.profiles.active=test --server.port=8888
输入指令如下:
测试的端口是9002,命令行的端口是8888,这里说明生效的是888.
大家进行测试后就会发现命令行设置的端口号优先级高(也就是使用的是命令行设置的端口号),配置的优先级其实SpringBoot 官网已经进行了说明,参见 :
官网设置
进入上面网站后会看到如下页面
如果使用了多种方式配置同一个配置项,优先级高的生效。
2.4.4多环境开发控制
以profile为例,如果Maven和Spring Boot都有profile,那么以Maven为主。
一般来说是Maven控制版本,Spring Boot加载Maven的版本。
创建Maven
Group:com.itheima
Artifact:springboot_05_maven_and_boot_profile
在pom.xml中增加
<profiles>
<!-- 开发环境 -->
<profile>
<id>dev</id>
<properties></properties>
</profile>
<!-- 测试环境 -->
<profile>
<id>test</id>
<properties></properties>
</profile>
<!-- 生产环境 -->
<profile>
<id>pro</id>
<properties></properties>
<!-- 默认启动 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
新建application.yml
#设置启用的环境
spring:
profiles:
active: dev
---
#开发
spring:
profiles: dev
server:
port: 9000
---
#生产
spring:
profiles: pro
server:
port: 9001
---
#测试
spring:
profiles: test
server:
port: 9002
相当于现在是Maven和SpringBoot的正面交锋,到底会采用哪个端口呢?
我们执行打包指令
去打包的文件夹中输入cmd指令
输入指令
java -jar springboot_05_maven_and_boot_profile-0.0.1-SNAPSHOT.jar
看一下启动的端口号是9000
发现生效的是application.yml的配置,这是为什么呢,和之前说的优先Maven配置好像不太一样啊,原来是我们在pom.xml中并没有指定名称。
修改pom.xml
<!-- 测试环境 -->
<profile>
<id>test</id>
<properties>
<profile.active>test</profile.active>
</properties>
</profile>
<!-- 生产环境 -->
<profile>
<id>pro</id>
<properties>
<profile.active>pro</profile.active>
</properties>
<activation>
<!-- 默认启动 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
修改profile
修改application.yml
代码如下
#设置启用的环境
spring:
profiles:
active: ${profile.active}
clean后再package
之后重复步骤,在jar包的文件夹中执行命令
java -jar springboot_05_maven_and_boot_profile-0.0.1-SNAPSHOT.jar
执行后发现端口是8080
这就更奇怪了,为啥会变成默认的8080端口呢,我们打开jar包的application.yml看一下,发现没有解析
修改application.yml
application.yml中对参数进行解析
配置如下:
<!-- 增加插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<encoding>UTF-8</encoding>
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration>
</plugin>
再重新clean和package一下
再重复上面的步骤重新去jar包所在的目录执行cmd
java -jar springboot_05_maven_and_boot_profile-0.0.1-SNAPSHOT.jar
这次如愿以偿,跑了正式库的9091端口
我们再看一下jar包中的配置文件application.yml
2.5 配置文件分类
有这样的场景,我们开发完毕后需要测试人员进行测试,由于测试环境和开发环境的很多配置都不相同,所以测试人员在运行我们的工程时需要临时修改很多配置,如下:
java –jar springboot.jar –-spring.profiles.active=test --server.port=85 --
server.servlet.context-path=/heima --server.tomcat.connection-timeout=-1 …… …… …… …… ……
针对这种情况, SpringBoot 定义了配置文件不同的放置的位置;而放在不同位置的优先级时不同的。
SpringBoot 中4级配置文件放置位置:
(级别低)
- 1级:classpath:application.yml
- 2级:classpath:config/application.yml
- 3级:file :application.yml
- 4级:file :config/application.yml
(级别高)
3级与4级留做系统打包后设置通用属性
1级和2级用于系统开发阶段设置通用属性
说明:级别越高优先级越高
2.5.1 代码演示
在这里我们只演示不同级别配置文件放置位置的优先级。
2.5.1.1 环境准备
创建一个名为 springboot_06_config_file 的 SpringBoot 工程,目录结构如下
Group:com.itheima
Artifact:springboot_06_config_file
在 resources 下创建一个名为 config 的目录,在该目录中创建 application.yml 配置文件,而在该配置文件中将端口号设置为 8001 ,内容如下
配置如下:
server:
port: 8001
而在 resources 下创建的 application.yml 配置文件中并将端口号设置为 8000 ,内容如下
server:
port: 8000
2.5.1.2 验证1级和2级的优先级
运行启动引导类,可以在控制台看到如下日志信息
通过这个结果可以得出类路径下的 config 下的配置文件优先于类路径下的配置文件。
所以我们可以给config中配置一个application.yml用于本地开发库的配置,自己debug代码,到测试库的时候,就把这里面的清空即可。
2.5.1.3 验证2级和4级的优先级
要验证4级,按照以下步骤完成
- 将工程打成 jar 包
点击工程的 package 来打 jar 包
- 在硬盘上找到 jar 包所在位置
- 在 jar 包所在位置创建 application.yml 配置文件,而在该配置文件中将端口号设置为 8002
在命令行使用以下命令运行程序:
java -jar springboot_06_config_file-0.0.1-SNAPSHOT.jar
输出结果如下:
发现新配置的application.yml的端口的优先级高。
- 在 jar 包所在位置创建 config 文件夹,在该文件夹下创建 application.yml 配置文件,而在该配置文件中将端口号设置为 8003
在命令行使用以下命令运行程序:
java -jar springboot_06_config_file-0.0.1-SNAPSHOT.jar
运行后日志信息如下
通过这个结果可以得出file: config 下的配置文件优先于类路径下的配置文件。
注意:
SpringBoot 2.5.0版本存在一个bug,我们在使用这个版本时,需要在 jar 所在位置的 config 目录下创建一个任意名称的文件夹。
3.SpringBoot整合junit
回顾 Spring 整合 junit
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {
@Autowired
private BookService bookService;
@Test
public void testSave(){
bookService.save();
}
}
使用 @RunWith 注解指定运行器,使用 @ContextConfiguration 注解来指定配置类或者配置文件。而 SpringBoot 整合junit 特别简单,分为以下三步完成
- 在测试类上添加 SpringBootTest 注解
- 使用 @Autowired 注入要测试的资源
- 定义测试方法进行测试
3.1 环境准备
创建一个名为 springboot_07_test 的 SpringBoot 工程,工程目录结构如下
Group:com.itheima
Artifact:springboot_07_test
这里不勾选spring web
看一下pom.xml
在 com.itheima.service 下创建 BookService 接口,内容如下
public interface BookService {
void save();
}
在 com.itheima.service.impl 包写创建一个 BookServiceImpl 类,使其实现 BookService 接口,内容如下
@Service
public class BookServiceImpl implements BookService {
@Override
public void save() {
System.out.println("BookServiceImpl.save()");
}
}
3.2 编写测试类
在 test/java 下创建 com.itheima 包,在该包下创建测试类,将 BookService 注入到该测试类中
Springboot07TestApplicationTests.java
@SpringBootTest
class Springboot07TestApplicationTests {
@Autowired
private BookService bookService;
@Test
void contextLoads() {
bookService.save();
}
}
运行测试类
注意:这里的引导类所在包必须是测试类所在包及其子包。
例如:
- 引导类所在包是 com.itheima
- 测试类所在包是 com.itheima
如果不满足这个要求的话,就需要在使用 @SpringBootTest 注解时,使用 classes 属性指定引导类的字节码对象。如
@SpringBootTest(classes = Springboot07TestApplication.class)
比如我们新建包test,将Springboot07TestApplicationTests.java移入
移入后再运行测试类,发现报错
修改Springboot07TestApplicationTests.java
增加属性值
代码如下:
@SpringBootTest(classes = Springboot07TestApplication.class)
再次运行,不再报错
4.SpringBoot整合mybatis
所以我们主要学习SpringBoot整合MyBatis
4.1 回顾Spring整合Mybatis
Spring 整合 Mybatis 需要定义很多配置类
- SpringConfig 配置类
- 导入 JdbcConfig 配置类
- 导入 MybatisConfig 配置类
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MyBatisConfig.class})
public class SpringConfig {
}
- JdbcConfig 配置类
定义数据源(加载properties配置项:driver、url、username、password)
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource getDataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
}
- MybatisConfig 配置类
定义 SqlSessionFactoryBean
定义映射配置
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.itheima.dao");
return msc;
}
@Bean
public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
ssfb.setTypeAliasesPackage("com.itheima.domain");
ssfb.setDataSource(dataSource);
return ssfb;
}
4.2 SpringBoot整合mybatis
4.2.1 创建模块
- 创建新模块,选择 Spring Initializr ,并配置模块相关基础信息
Group:com.itheima
Artifact:springboot_08_mybatis
- 选择当前模块需要使用的技术集(MyBatis、MySQL)
上面的版本更改为2.7.8,如果没有更改,后续更改pom.xml也可以
依赖中新增的就是我们打勾的
4.2.2 定义实体类
在 com.itheima.domain 包下定义实体类 Book ,内容如下
public class Book {
private Integer id;
private String name;
private String type;
private String description;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", type='" + type + '\'' +
", description='" + description + '\'' +
'}';
}
}
4.2.3 定义dao接口
在 com.itheima.dao 包下定义 BookDao 接口,内容如下
@Repository
public interface BookDao {
@Select("select * from tbl_book where id = #{id}")
public Book getById(Integer id);
}
4.2.4 定义测试类
在 test/java 下定义包 com.itheima ,在该包下测试类,内容如下
@SpringBootTest
class Springboot08MybatisApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
Book book = bookDao.getById(1);
System.out.println("book:"+book);
}
}
4.2.5 编写配置
我们代码中并没有指定连接哪儿个数据库,用户名是什么,密码是什么。所以这部分需要在 SpringBoot 的配置文件中进行配合。
在 application.yml 配置文件中配置如下内容:
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: hsp
4.2.6 测试
运行测试方法,我们会看到如下错误信息
错误信息显示在 Spring 容器中没有 BookDao 类型的 bean 。为什么会出现这种情况呢?
原因是 Mybatis 会扫描接口并创建接口的代码对象交给 Spring 管理,但是现在并没有告诉 Mybatis 哪个是 dao 接口。而我们要解决这个问题需要在 BookDao 接口上使用 @Mapper , BookDao 接口改进为:
@Mapper
public interface BookDao {
@Select("select * from tbl_book where id = #{id}")
public Book getById(Integer id);
}
运行测试类
与数据库一致
注意:
SpringBoot 版本低于2.4.3(不含),Mysql驱动版本大于8.0时,需要在url连接串中配置时区jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC ,或在MySQL数据库端配置时区解决此问题。
此时我们的数据源是默认的,如果我们想用德鲁伊呢
4.2.7 使用Druid数据源
现在我们并没有指定数据源, SpringBoot 有默认的数据源,我们也可以指定使用 Druid 数据源,按照以下步骤实现
<!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
- 在 application.yml 配置文件配置
可以通过 spring.datasource.type 来配置使用什么数据源。配置文件内容可以改进为
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db
username: root
password: hsp
type: com.alibaba.druid.pool.DruidDataSource
再重新测试一下,成功输出
这里mysql8之后需要更改配置
spring:
datasource:
#driver-class-name: com.mysql.jdbc.Driver
driver-class-name: com.mysql.cj.jdbc.Driver
#url: jdbc:mysql://localhost:3306/ssm_db
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: hsp
type: com.alibaba.druid.pool.DruidDataSource
更改之后警告就没了。
5.案例
SpringBoot 到这就已经学习完毕,接下来我们将学习 SSM 时做的三大框架整合的案例用 SpringBoot 来实现一下。我们
完成这个案例基本是将之前做的拷贝过来,修改成 SpringBoot 的即可,主要从以下几部分完成
- pom.xml
配置起步依赖,必要的资源坐标(druid)
- application.yml
设置数据源、端口等
- 配置类
全部删除
- dao
设置@Mapper
- 测试类
- 页面
放置在resources目录下的static目录中
5.1 创建工程
创建 SpringBoot 工程,在创建工程时需要勾选 web 、 mysql 、 mybatis ,工程目录结构如下
Group:com.itheima
Artifact:springboot_09_ssm
勾选3个
由于我们工程中使用到了 Druid ,所以需要导入 Druid 的坐标
pom.xml
<!--Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
更改spring boot的版本
确认无误即可
5.2 代码拷贝
将 springmvc_11_page 工程中的 java 代码及测试代码连同包拷贝到 springboot_09_ssm 工程,按照下图进行拷贝。
需要修改的内容如下:
-
Springmvc_11_page 中 config 包下的是配置类,而 SpringBoot 工程不需要这些配置类,所以这些可以直接删除
-
dao 包下的接口上在拷贝到 springboot_09-ssm 工程中需要在接口中添加 @Mapper 注解
-
BookServiceTest 测试需要改成 SpringBoot 整合 junit 的。
@SpringBootTest
public class BookServiceTest {
@Autowired
private BookService bookService;
@Test
public void testGetById(){
Book book = bookService.getById(1);
System.out.println(book);
}
@Test
public void testGetAll(){
List<Book> all = bookService.getAll();
System.out.println(all);
}
}
5.3 配置文件
在 application.yml 配置文件中需要配置如下内容
spring:
datasource:
#driver-class-name: com.mysql.jdbc.Driver
driver-class-name: com.mysql.cj.jdbc.Driver
#url: jdbc:mysql://localhost:3306/ssm_db
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: hsp
type: com.alibaba.druid.pool.DruidDataSource
server:
port: 9000
先跑一下测试类
5.4 静态资源
在 SpringBoot 程序中是没有 webapp 目录的,那么在 SpringBoot 程序中静态资源需要放在什么位置呢?
静态资源需要放在 resources 下的 static 下,如下图所示
启动Springboot09SsmApplication.java
输入网址
http://localhost:9000/pages/books.html
跳转成功
新建一个首页index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1></h1>
<script>
document.location.href="pages/books.html"
</script>
</body>
</html>
之后重启
输出地址
http://localhost:9000/
回车后即可跳转