SpringBoot(2)打包和日志

打包与运行

实际开发完成后,我们的项目是不可能运行在自己的电脑上的,需要运行在专用的服务器上的。这就要将我们的程序先组织成一个文件,然后将这个文件传输到这台服务器上。这里面就存在两个过程,一个是打包的过程,另一个是运行的过程。

程序打包与运行(windows)

SpringBoot程序是基于Maven创建的,在Maven中提供有打包的指令,叫做package。

mvn package

在这里插入图片描述

也可以直接使用maven插件:
在这里插入图片描述
打包后会产生一个与工程名类似的jar文件,其名称是由模块名+版本号+.jar组成的。
在这里插入图片描述

程序包打好以后,在程序包所在路径下,执行指令,程序正常运行,与在Idea下执行程序没有区别。

java -jar 工程包名.jar

在这里插入图片描述
注意: 如果计算机中没有安装java的jdk环境,是无法正确执行上述操作的,因为程序执行使用的是java指令。
​注意: 在使用向导创建SpringBoot工程时,pom.xml文件中会有如下配置,这一段配置千万不能删除,否则打包后无法正常执行程序。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

SpringBoot程序打包失败处理

打包以后执行会下面的问题,导致程序无法正常执行:
在这里插入图片描述
在SpringBoot工程的pom.xml中有下面这组配置,这组配置决定了打包出来的程序包是否可以执行。

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

可执行jar包的目录结构:
在这里插入图片描述
lib目录中jar文件都是制作这个工程时导入的坐标对应的文件。SpringBoot程序为了让自己打包生成的程序可以独立运行,不仅将项目中自己开发的内容进行了打包,还把当前工程运行需要使用的jar包全部打包进来了。就是为了可以独立运行。不依赖程序包外部的任何资源可以独立运行当前程序。

其中MANIFEST.MF文件内容如下

Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Implementation-Title: springboot_08_ssmp
Implementation-Version: 0.0.1-SNAPSHOT
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Start-Class: com.itheima.SSMPApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.5.4
Created-By: Maven Jar Plugin 3.2.0
Main-Class: org.springframework.boot.loader.JarLauncher ##jar启动器
  1. SpringBoot程序添加配置后会打出一个特殊的包,包含Spring框架部分功能,原始工程内容,原始工程依赖的jar包
  2. 首先读取MANIFEST.MF文件中的Main-Class属性,用来标记执行java -jar命令后运行的类
  3. JarLauncher类执行时会找到Start-Class属性,也就是启动类类名
  4. 运行启动类时会运行当前工程的内容
  5. 运行当前工程时会使用依赖的jar包,从lib目录中查找

命令行启动常见问题及解决方案:

# 查询端口
netstat -ano
# 查询指定端口
netstat -ano |findstr "端口号"
# 根据进程PID查询进程名称
tasklist |findstr "进程PID号"
# 根据PID杀死任务
taskkill /F /PID "进程PID号"
# 根据进程名称杀死任务
taskkill -f -t -im "进程名称"

程序打包与运行(linux)

  • 基于Linux(CenterOS7)
  • 安装JDK,且版本不低于打包时使用的JDK版本,确保运行环境有效
  • 安装包保存在/usr/local/自定义目录中或$HOME下
  • 其他操作参照Windows版进行

高级配置

临时属性设置

SpringBoot提供了灵活的配置方式,如果发现项目中有个别属性需要重新配置,可以使用临时属性的方式快速修改某些配置。在启动的时候添加上对应参数就可以。

java –jar springboot.jar –-server.port=80

当属性存在多级名称时,中间使用点分隔,和properties文件中的属性格式完全相同。

java –jar springboot.jar –-server.port=80 --logging.level.root=debug

属性加载优先级
打开官方文档中对应的内容,就可以查看配置读取的优先顺序:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config
在这里插入图片描述
总结:

  1. 使用jar命令启动SpringBoot工程时可以使用临时属性替换配置文件中的属性
  2. 临时属性添加方式:java –jar 工程名.jar –-属性名=值
  3. 多个临时属性之间使用空格分隔
  4. 临时属性必须是当前boot工程支持的属性,否则设置无效

开发环境中使用临时属性

打开SpringBoot引导类的运行界面,在里面找到配置项。其中Program arguments对应的位置就是添加临时属性的,可以加几个试试效果。
在这里插入图片描述
如果对java编程熟悉的小伙伴应该知道,运行main方法的时候,如果想使用main方法的参数,也就是下面的args参数,就是在上面这个位置添加的参数。

public static void main(String[] args) {
}

原来是通过args就可以获取到参数。再来看引导类是如何书写的:

public static void main(String[] args) {
    SpringApplication.run(SSMPApplication.class,args);
}

这个args参数居然传递给了run方法,看来在Idea中配置的临时参数就是通过这个位置传递到我们的程序中的。言外之意,这里如果不用这个args是不是就断开了外部传递临时属性的入口呢?是这样的,我们可以使用下面的调用方式,这样外部临时属性就无法进入到SpringBoot程序中了。

public static void main(String[] args) {
    SpringApplication.run(SSMPApplication.class);
}

或者还可以使用如下格式来玩这个操作,就是将配置不写在配置文件中,直接写成一个字符串数组,传递给程序入口。当然,这种做法并没有什么实际开发意义。

public static void main(String[] args) {
    public static void main(String[] args) {
        String[] arg = new String[1];
        arg[0] = "--server.port=8083";
        SpringApplication.run(SSMPApplication.class, arg);
    }
}

在这里插入图片描述

配置文件分类

SpringBoot提供的4级配置文件分别是:

  • 类路径下配置文件(一直使用的是这个,也就是resources目录中的application.yml文件)
  • 类路径下config目录下配置文件
  • 程序包所在目录中配置文件
  • 程序包所在目录中config目录下配置文件

在这里插入图片描述
在这里插入图片描述
上面4个文件的加载优先顺序为

  1. file :config/application.yml 【最高】
  2. file :application.yml
  3. classpath:config/application.yml
  4. classpath:application.yml 【最低】

8085>8084>8083>80

总结

  1. 配置文件分为4种

    • 项目类路径配置文件:服务于开发人员本机开发与测试
    • 项目类路径config目录中配置文件:服务于项目经理整体调控
    • 工程路径配置文件:服务于运维人员配置涉密线上环境
    • 工程路径config目录中配置文件:服务于运维经理整体调控
  2. 多层级配置文件间的属性采用叠加并覆盖的形式作用于程序

自定义配置文件

自定义配置文件方式有如下两种:

方式一:使用临时属性设置配置文件名,注意仅仅是名称,不要带扩展名
在这里插入图片描述
方式二:使用临时属性设置配置文件路径,这个是全路径名
在这里插入图片描述
也可以设置加载多个配置文件:
在这里插入图片描述
总结

  1. 配置文件可以修改名称,通过启动参数设定
  2. 配置文件可以修改路径,通过启动参数设定
  3. 微服务开发中配置文件通过配置中心进行设置

多环境开发

yaml单一文件版

针对不同的环境设置不同的配置属性即可。比如开发时配置端口如下:

## 设置默认启动哪个配置
spring:
	config:
    	activate:
        	on-profile: pro
## 中间使用三个减号分隔开不同环境
---
## 起别名区分不同环境
spring:
	profiles: pro
server:
	port: 80
---
spring:
	profiles: dev
server:
	port: 81
---
spring:
	profiles: test
server:
	port: 82

总结

  1. 多环境开发需要设置若干种常用环境,例如开发、生产、测试环境
  2. yaml格式中设置多环境使用—区分环境设置边界
  3. 每种环境的区别在于加载的配置属性不同
  4. 启用某种环境时需要指定启动时使用该环境

yaml多文件版

将所有的配置都放在一个配置文件中,尤其是每一个配置应用场景都不一样,这显然不合理,于是就有了将一个配置文件拆分成多个配置文件的想法。拆分后,每个配置文件中写自己的配置,主配置文件中写清楚用哪一个配置文件就好了。
主配置文件:

spring:
	profiles:
		active: pro		# 启动pro

环境配置文件因为每一个都是配置自己的项,所以连名字都不用写里面了。使用文件名区分区分配置。
application-pro.yaml

server:
	port: 80

application-dev.yaml

server:
	port: 81

文件的命名规则为:application-环境名.yml。

在配置文件中,如果某些配置项所有环境都一样,可以将这些项写入到主配置中,只有哪些有区别的项才写入到环境配置文件中。

  • 主配置文件中设置公共配置(全局)
  • 环境分类配置文件中常用于设置冲突属性(局部)

备注: properties文件多环境配置仅支持多文件格式

多环境开发控制-配置文件

如何基于多环境开发做配置独立管理,首先将所有的配置根据功能对配置文件中的信息进行拆分,并制作成独立的配置文件,命名规则如下

  • application-devDB.yml
  • application-devRedis.yml
  • application-devMVC.yml

使用include属性在激活指定环境的情况下,同时对多个环境进行加载使其生效,多个环境间使用逗号分隔

spring:
	profiles:
    	active: dev
        include: devMVC,devDB

application-dev.yml(加载顺序为3,主配置最后加载)

server:
  port: 80

application-devDB.yml(加载顺序为1,先写先加载)

server:
  port: 81

application-devMVC.yml(加载顺序为2,后写后加载)

server:
  servlet:
    context-path: /ebank
  port: 82

在这里插入图片描述
注意: 当主环境dev与其他环境有相同属性时,主环境属性生效;其他环境中有相同属性时,最后加载的环境属性生效。

但是上面的设置也有一个问题,比如要切换dev环境为pro时,include也要修改。因为include属性只能使用一次,这就比较麻烦了。

SpringBoot从2.4版开始使用group属性替代include属性,降低了配置书写量。主配置先加载

spring:
	profiles:
    	active: dev
        group:
        	"dev": devDB,devMVC
      		"pro": proDB,proRedis,proMVC
      		"test": testDB,testRedis,testMVC

在这里插入图片描述

多环境开发控制-maven

maven和SpringBoot同时设置多环境的话怎么办?
maven是做什么的?项目构建管理的,最终生成代码包的,SpringBoot是干什么的?简化开发的。简化,又不是其主导作用。最终还是要靠maven来管理整个工程,所以SpringBoot应该听maven的。整个确认后下面就好做了。大体思想如下:

  • 先在maven环境中设置用什么具体的环境
  • 在SpringBoot中读取maven设置的环境即可

maven中设置多环境(使用属性方式区分环境):

<profiles>
    <profile>
        <id>env_dev</id>
        <properties>
            <profile.active>dev</profile.active>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>		<!--默认启动环境-->
        </activation>
    </profile>
    <profile>
        <id>env_pro</id>
        <properties>
            <profile.active>pro</profile.active>
        </properties>
    </profile>
</profiles>

SpringBoot中读取maven设置值:

spring:
	profiles:
    	active: @profile.active@
    	   "dev": devDB,devMVC
      	   "pro": proDB,proRedis,proMVC

总结

  1. 当Maven与SpringBoot同时对多环境进行控制时,以Mavn为主,SpringBoot使用@…@占位符读取Maven对应的配置属性值
  2. 基于SpringBoot读取Maven配置属性的前提下,如果在Idea下测试工程时pom.xml每次更新需要手动compile方可生效

日志

日志其实就是记录程序日常运行的信息,主要作用如下:

  • 编程期调试代码
  • 运营期记录信息
    • 记录日常运营重要信息(峰值流量、平均响应时长……)
    • 记录应用报错信息(错误堆栈)
    • 记录运维过程数据(扩容、宕机、报警……)

代码中使用日志工具

1.添加日志记录操作

@RestController
@RequestMapping("/books")
public class BookController extends BaseClass{
	//创建记录日志的对象
    private static final Logger log = LoggerFactory.getLogger(BookController.class);
    @GetMapping
    public String getById(){
    	//记录日志
        log.debug("debug...");
        log.info("info...");
        log.warn("warn...");
        log.error("error...");
        return "springboot is running...2";
    }
}

2.设置日志输出级别
可以根据日志的级别来设置哪些参与记录的。日志的级别分为6种,分别是:

  • TRACE:运行堆栈信息,使用率低
  • DEBUG:程序员调试代码使用
  • INFO:记录运维过程数据
  • WARN:记录运维过程报警数据
  • ERROR:记录错误堆栈信息
  • FATAL:灾难信息,合并计入ERROR

一般情况下,开发时候使用DEBUG,上线后使用INFO,运维信息记录使用WARN即可。日志系统通常都提供了细粒度的控制:

# 开启debug模式,输出调试信息,常用于检查系统运行状况
debug: true

# 设置日志级别,root表示根节点,即整体应用日志级别
logging:
	level:
    	root: debug

3.设置日志组,控制指定包对应的日志输出级别,也可以直接控制指定包对应的日志输出级别

logging:
	# 设置日志组
    group:
    	# 自定义组名,设置当前组中所包含的包
        ebank: com.itheima.controller
    level:
    	root: warn
        # 为对应组设置日志级别
        ebank: debug
    	# 为对包设置日志级别
        com.itheima.controller: debug

总结

  1. 日志用于记录开发调试与运维过程消息
  2. 日志的级别共6种,通常使用4种即可,分别是DEBUG,INFO,WARN,ERROR
  3. 可以通过日志组或代码包的形式进行日志显示级别的控制

优化日志对象创建代码

导入lombok后使用注解搞定,日志对象名为log

@Slf4j		//这个注解替代了下面那一行
@RestController
@RequestMapping("/books")
public class BookController extends BaseClass{
    //private static final Logger log = LoggerFactory.getLogger(BookController.class);	//这一句可以不写了
     @GetMapping
    public String getById(){
        log.debug("debug...");
        log.info("info...");
        log.warn("warn...");
        log.error("error...");
        return "springboot is running...2";
    }
}

日志输出格式控制

日志已经能够记录了,但是目前记录的格式是SpringBoot给我们提供的,如果想自定义控制就需要自己设置了。先分析一下当前日志的记录格式。
在这里插入图片描述
于单条日志信息来说,日期,触发位置,记录信息是最核心的信息。级别用于做筛选过滤,PID与线程名用于做精准分析。了解这些信息后就可以DIY日志格式了。下面给出课程中模拟的官方日志模板的书写格式,便于大家学习。

#日志模板
logging:
	pattern:
    	console: "%d %clr(%5p) --- [%16t] %clr(%-40.40c){cyan} : %m %n"
    	# 时间 显示颜色,占位5 --- [占位16线程名] 显示颜色(左对齐,类名截取40位长):消息 换行

日志文件

日志不能仅显示在控制台上,要把日志记录到文件中,方便后期维护查阅。对于日志文件的使用存在各种各样的策略,例如每日记录,分类记录,报警后记录等(后续再说)。
​记录日志到文件中格式非常简单,设置日志文件名即可。

logging:
	file:
    	name: server.log

虽然使用上述格式可以将日志记录下来了,但是面对线上的复杂情况,一个文件记录肯定是不能够满足运维要求的,通常会每天记录日志文件,同时为了便于维护,还要限制每个日志文件的大小。下面给出日志文件的常用配置方式:

logging:
	logback:
    	rollingpolicy:
        	max-file-size: 10MB
            file-name-pattern: server.%d{yyyy-MM-dd}.%i.log

要求容量到达3KB以后就转存信息到第二个文件中。文件命名规则中的%d标识日期,%i是一个递增变量,用于区分日志文件。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值