- Springboot运维实用篇
- Springboot工程打包与运行
- 配置高级
- 多环境开发
- 日志
二、运维实用篇
2.1 Springboot工程打包与运行
2.1.1 程序打包
对 Springboot 的 maven 工程进行打包很简单:
通过
clean
清楚之前的target
目录。省略打包过程中的测试环节(前提是对已经开发的功能都进行过测试且测试通过),通过点击 ② 处的按钮省略,目的是为了防止测试过程对数据库的数据造成影响。
通过
package
对工程进行打包。生成的jar
包就在target
目录下。我们可以通过在命令行输入
java -jar xxx.jar
来运行项目。注意:
jar
支持命令行启动需要依赖 maven 插件支持,请确认打包时是否具有 SpringBoot 对应的 maven 插件:1
2
3
4
5
6
7
8<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.2.2 maven打包插件
由前所述,
jar
支持命令行启动需要依赖 maven 插件支持,为什么呢?我们可以尝试在使用该 maven 插件前后,分别打包 springboot 项目,观察得到的
jar
包有什么不同。使用 maven 插件打包的
jar
包(后缀为 1),后面简称为1包
没有使用 maven 插件打包的
jar
包(后缀为 2),后面简称为2包
可以看到:
1包
的大小要明显大于2包
,因为在1包
中,还打包了依赖的jar
包以及项目启动类加载器等包。而2包
中只有项目代码相关的包,不会加入依赖的jar
包和启动类加载器等包。1包
和2包
的目录结构不一样,实际上,2包
中的内容只是1包
中的一部分。在
META-INF
目录中,有jar
包的描述文件MANIFEST.MF
。1包
的MANIFEST.MF
:1
2
3
4
5
6
7
8
9
10
11
12Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.6.1
Built-By: Running Noob
Build-Jdk: 17.0.8
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.f.springboot.Springboot06SsmpApplication
Spring-Boot-Version: 3.0.2
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx2包
的MANIFEST.MF
:1
2
3
4
5Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.6.1
Built-By: Running Noob
Build-Jdk: 17.0.8
在
1包
的MANIFEST.MF
中,指明了JarLauncher
类(jar 启动器,在org
包中)和启动类Springboot06SsmpApplication
,由此才能找到项目启动的入口。
对
1包
的各目录的作用做一个简要说明:BOOT-INF
目录下存放程序员开发的项目相关代码的classes
文件以及依赖的jar
包。META-INF
目录下存放jar
包的相关元数据。org
目录下存放用来独立加载运行 springboot 项目的相关类的classes
文件。
2.2.3 在Linux服务器上运行项目
在实际开发中,项目基本都在 Linux 服务器上运行,所以我们要将之前打包的
jar
包放到 Linux 服务器上面运行。这里以 Ubuntu 64 位操作系统为例。
在Linux服务器上运行项目需要一些前置条件:
- 安装 JDK,且版本不低于打包时使用的 JDK 版本,这里是安装 JDK 17。
- 安装 MySQL。
安装包保存在
/usr/local/自定义目录
下或$HOME
下。然后通过以下命令运行项目的
jar
包即可:1
sudo java -jar /usr/local/app/springboot_06_ssmp-0.0.1-SNAPSHOT1.jar
2.2 配置高级
2.2.1 临时属性设置(有风险,不用)
如果想要临时修改项目的属性配置,例如将项目的
application.yml
中设置的 80 端口改为 8080 端口,则可以在命令行中,通过在命令末尾带上属性来启动 springboot 项目:1
sudo java -jar /usr/local/app/springboot_06_ssmp-0.0.1-SNAPSHOT1.jar --server.port=8080
注意使用临时属性时,要用
properties
中属性配置的格式。要携带多个临时属性启动 SpringBoot 时,属性间使用空格分隔:
1
sudo java -jar /usr/local/app/springboot_06_ssmp-0.0.1-SNAPSHOT1.jar --server.port=8080 --xxx=xxx
属性加载的优先级顺序:
事实上,在命令行后面带上的临时属性,其实就是传给引导类的
args
参数:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15package com.f.springboot;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
public class Springboot06SsmpApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot06SsmpApplication.class, args);
}
}为了提高安全性,可以在方法中将
args
参数去掉:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package com.f.springboot;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
public class Springboot06SsmpApplication {
public static void main(String[] args) {
// 可以在启动boot程序时断开读取外部临时配置对应的入口,也就是去掉读取外部参数的形参
SpringApplication.run(Springboot06SsmpApplication.class);
}
}
2.2.2 ★配置环境
springboot的4级配置文件
在实际项目开发中,至少有两套环境:开发环境和生产环境(其实还有一个测试环境)。
- 开发环境是我们程序员在开发时的环境,这时我们有一套开发配置。
- 生产环境是项目实际上线的环境,这时有另一套配置。
问题是配置的名称都为
application.(properties|yml|yaml)
,在编写开发环境的配置文件和生产环境的配置文件时,名称会冲突。怎么办?springboot 可以让我们基于现有的配置,再做一套配置,这套新做的配置,可以覆盖现有的配置。步骤为:
在类的根路径下,也是
resources
目录下,新建config
目录。在
config
目录下创建新的配置文件application.yml
,做一套全新的配置:1
2
3# 应用服务 WEB 访问端口
server:
port: 8888作为对比,这是原先开发环境中的配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# 应用服务 WEB 访问端口
server:
port: 80
# 数据源配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
# mybatis-plus配置
mybatis-plus:
global-config:
db-config:
table-prefix: t_
id-type: auto # 使用数据库默认的自增策略
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
启动项目,发现端口变为 8888,且项目正常运行。
这两套配置文件之间的合作原则:
- 重合的部分,级别高的配置(
resources/config
目录中的)覆盖级别低的配置(resources
目录中的)。
- 重合的部分,级别高的配置(
不重合的部分,配置都会生效,即“合并在一起”了。
多层级配置文件间的属性采用叠加并覆盖的形式作用于程序。
前面是在类的根路径下新建
config
目录,然后创建配置文件,该配置文件优先级高于最原始的配置文件。当项目打包成
jar
包以后,如果在jar
包的同级目录下创建了配置文件,则该配置文件的优先级又要高于类路径下的配置文件。- 类似的,在
jar
包的同级目录下新建config
目录,然后创建配置文件,则该配置文件优先级高于前面所有的配置文件。
- 类似的,在
最终可以发现,SpringBoot 中有 4 级配置文件:
- 1 级:
file:config/application.yml
【最高】 - 2 级:
file:application.yml
- 3 级:
classpath:config/application.yml
- 4 级:
classpath:application.yml
【最低】
作用:
- 1 级与 2 级留做系统打包成
jar
包后设置通用属性,1 级常用于运维经理进行线上整体项目部署方案调控。 - 3 级与 4 级用于系统开发阶段设置通用属性,3 级常用于项目经理进行整体项目属性调控。
- 1 级:
之前说过,配置文件的优先级为
properties
(最高)>yml
>yaml
(最低),那么问题来了,是classpath:config/application.yml
的优先级高,还是classpath:application.properties
的优先级高?- 测试发现,
classpath:config/application.yml
的优先级高,说明从优先级上来说,目录的优先级高于配置文件格式类型的优先级。
- 测试发现,
2.2.3 自定义配置文件名称(实际开发中用的少)
配置文件的名称只能是
application.(properties|yml|yaml)
吗,如果是这样,那配置文件的名称相当于直接暴露在外面,有风险性。application.(properties|yml|yaml)
是 springboot 工程默认的配置文件名称,但其实我们可以自定义配置文件的名称。有两种办法来自定义。- 假设我们自定义的配置文件名称为
bookconfig.yml
- 假设我们自定义的配置文件名称为
方法一:通过临时属性指定自定义的配置文件名称(无需书写配置文件扩展名)。
--spring.config.name=bookconfig
方法二:通过临时属性指定文件路径下的配置文件(需要书写配置文件扩展名)。
--spring.config.location=classpath:bookconfig.yml
注意:指定文件路径下的配置文件时可以指定多个配置,然后后面的会覆盖前面的:
--spring.config.location=classpath:bookconfig.yml,classpath:book-server.yml
- 会使用
book-server.yml
配置。
- 会使用
自定义配置文件的说明:
- 单服务器项目:使用自定义配置文件需求较低。
- 多服务器项目:使用自定义配置文件需求较高,将所有配置放置在一个目录中,统一管理。
- 基于 SpringCloud 技术,所有的服务器将不再设置配置文件,而是通过配置中心进行设定,动态加载配置信息。
2.3 ★多环境开发
多环境:生产环境、开发环境、测试环境。
不同环境的配置各不相同。
- 所谓多环境开发,就是根据不同的环境配置不同的值。
下面我们设置了三种不同的环境,并用
---
隔开:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30# 要应用的环境
# 可以在这里写一些公共配置
spring:
profiles:
active: dev
---
# 下面设置了三种不同的环境,用"---"隔开
# 生产环境
spring:
config:
activate:
on-profile: pro
server:
port: 80
---
# 开发环境
spring:
config:
activate:
on-profile: dev
server:
port: 81
---
# 测试环境
spring:
config:
activate:
on-profile: test
server:
port: 82另外,应用环境也要用
---
和设置的环境隔开。在应用环境中写一些公共配置,在设置的环境中写该环境专有的配置。
图中是过时的写法,具体写法还是看上面的代码。
在实际开发中,不会将多环境的配置都写在一个文件中,而是将不同环境的配置用不同的文件来存储。
2.3.1 多环境开发多文件版(yaml)
其实就是将多环境的配置从一个文件拆分为多个文件:
1
2
3# application-pro.yml文件
server:
port: 801
2
3# application-dev.yml文件
server:
port: 811
2
3# application-test.yml文件
server:
port: 821
2
3
4
5# application.yml文件
# 应用环境
spring:
profiles:
active: dev- 注意环境配置文件的命名为
application-xxx.yml
- 注意环境配置文件的命名为
2.3.2 多环境开发多文件版(properties)
- 和
yaml
版的基本一模一样。
2.3.3 ★多环境开发配置文件书写技巧
多环境开发配置文件书写技巧:
- 主配置文件中设置公共配置(全局)
- 环境分类配置文件中常用于设置冲突属性(局部)
根据功能对配置文件中的信息进行进一步拆分,并制作成独立的配置文件,命名规则如下:
application-devDB.yml
-> 开发环境下数据库配置文件application-devRedis.yml
-> 开发环境下缓存配置文件application-devMVC.yml
-> 开发环境下MVC配置文件
使用
include
属性在激活指定环境的情况下,同时对多个环境进行加载使其生效,多个环境间使用逗号分隔:1
2
3
4spring:
profiles:
active: dev
include: devDB,devMVC注意:当主环境
dev
与其他环境有相同属性时,主环境属性生效;其他环境中有相同属性时,最后加载的环境属性生效。1
The following profiles are active: devDB,devMVC,dev
- 生效优先级:dev > devMVC > devDB
从 Spring2.4 版开始使用
group
属性替代include
属性,降低了配置书写量:1
2
3
4
5
6
7spring:
profiles:
active: dev
group:
"dev": devDB,devMVC
"pro": proDB,proMVC
"test": testDB,testRedis,testMVC使用
group
属性定义多种主环境与子环境的包含关系。注意:使用
group
属性,会覆盖主环境dev (active)
的内容,最后加载的环境属性生效。1
The following 3 profiles are active: "dev", "devDB", "devMVC"
- 生效优先级:devMVC > devDB > dev
2.4 ★日志
- 日志的作用:
- 编程期调试代码。
- 运营期记录信息。
- 记录日常运营重要信息(峰值流量、平均响应时长……)
- 记录应用报错信息(错误堆栈)
- 记录运维过程数据(扩容、宕机、报警……)
- 代码中使用日志工具记录日志。
2.4.1 日志基础操作
使用日志记录信息分以下几步:
创建日志记录对象。
手工记录日志信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package com.f.springboot.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author fzy
* @date 2024/2/21 15:30
*/
public class BookController {
// 1.创建记录日志对象
private static final Logger log = LoggerFactory.getLogger(BookController.class);
public String get() {
// 2.手工记录日志信息
log.trace("trace...");
log.debug("debug...");
log.info("info...");
log.warn("warn...");
log.error("error...");
return "springboot2...";
}
}日志级别:
TRACE < DEBUG < INFO < WARN < ERROR < FATAL
TRACE
:运行堆栈信息,使用率低DEBUG
:程序员调试代码使用INFO
:记录运维过程数据WARN
:记录运维过程报警数据ERROR
:记录错误堆栈信息FATAL
:灾难信息,合并计入ERROR
在
Mybatis笔记 - 2.5 Mybatis集成日志框架logback
、Spring笔记 - 3.4 Spring6 启用 Log4j2 日志框架
中均有提到日志相关内容。
在
application.yml
文件中设置日志输出的级别,该级别及该级别之上的日志将会被记录:1
2
3
4
5# 设置日志记录级别为DEBUG
# root 表示根节点,即整体应用日志级别
logging:
level:
root: debug除了设置
root
的日志输出级别,还可以设置日志组,控制指定组对应的日志输出级别,也可以直接控制指定包对应的日志输出级别:1
2
3
4
5
6
7
8
9
10
11# 设置日志组,控制指定组对应的日志输出级别
logging:
group:
# 自定义组名,设置组中所包含的包
controller: com.f.springboot.controller
model: com.f.springboot.service, com.f.springboot.mapper
level:
root: info
# 设置某个组的日志输出级别
controller: debug
model: debug
快速创建日志对象
使用
lombok
提供的注解@Slf4j
简化开发,减少日志对象的声明操作。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package com.f.springboot.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author fzy
* @date 2024/2/21 15:30
*/
public class BookController {
// 1.使用@Slf4j创建记录日志对象
//private static final Logger log = LoggerFactory.getLogger(BookController.class);
public String get() {
// 2.手工记录日志
log.trace("trace...");
log.debug("debug...");
log.info("info...");
log.warn("warn...");
log.error("error...");
return "springboot2...";
}
}
2.4.2 日志输出格式控制
日志在默认格式下,有以下几个部分组成:
PID
:进程 ID,用于表明当前操作所处的进程,当多服务同时记录日志时,该值可用于协助程序员调试程序。- 所属类/接口名:当前显示信息为 SpringBoot 重写后的信息,类的全名称过长时,简化包名书写为首字母,甚至直接删除。
我们可以在
application.yml
配置文件中自定义日志的输出格式(不重要):1
2
3
4# 设置日志输出的格式
logging:
pattern:
console: "%d - %m%n"%d
:日期%m
:消息%n
:换行
2.4.3 文件记录日志
通过在
application.yml
配置文件中设置记录日志的文件:1
2
3
4
5
6
7
8
9
10# 设置记录日志的文件
logging:
file:
name: server.log
logback:
rollingpolicy:
# 当日志大小超过4KB时,就新开一个日志文件
max-file-size: 4KB
# 日志名称的设置
file-name-pattern: server.%d{yyyy-MM-dd}.%i.log- 日志文件会被保存在整个项目的根路径下。