2.SpringBoot运维实用篇

SpringBoot运维实用篇

​ 下面就从运维实用篇开始讲,在运维实用篇中,我给学习者的定位是玩转配置,为开发实用篇中做各种技术的整合做好准备工作。

主要分为以下内容:

  • SpringBoot程序的打包与运行
  • 配置高级
  • 多环境开发
  • 日志

​ 下面开启第一部分SpringBoot程序打包与运行的学习

YW-1.程序打包

打包适合做完工程之后,将项目跑在服务器上

​ 那我们的程序如何放置在这台专用的电脑上呢,这就要将我们的程序先组织成一个文件,然后将这个文件传输到这台服务器上。这里面就存在两个过程,一个是打包的过程,另一个是运行的过程。

一般流程:

  1. 开发部门使用Git、SVN等版本控制工具上传工程到版本服务器
  2. 服务器使用版本控制工具下载工程
  3. 服务器上使用Maven工具在当前真机环境下重新构建项目
  4. 启动服务

​ 打包指将程序转换成一个可执行的文件,所谓运行指不依赖开发环境执行打包产生的文件。

程序打包

​ SpringBoot程序是基于Maven创建的,在Maven中提供有打包的指令,叫做package。本操作可以在Idea环境下执行。

mvn package

​ 打包后会产生一个与工程名类似的jar文件,其名称是由模块名+版本号+.jar组成的。

程序运行

​ 程序包打好以后,就可以直接执行了。在程序包所在路径下,执行指令。

java -jar 工程包名.jar

​ 执行程序打包指令后,程序正常运行,与在Idea下执行程序没有区别。

特别关注:在使用向导创建SpringBoot工程时,pom.xml文件中会有如下配置插件,这一段配置是专门为spring boot工程配置的,不能删除,否则无法运行jar包

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

image-20230327193914358

总结

  1. SpringBoot工程可以基于java环境下独立运行jar文件启动服务
  2. SpringBoot工程执行mvn命令package进行打包
  3. 执行jar命令:java –jar 工程名.jar

SpringBoot程序打包失败处理⭐️

image-20211201094223991

.jar文件工作机制

​ 搞java开发平时会接触很多jar包,比如mysql的驱动jar包,而上面我们打包程序后得到的也是一个jar文件。这个时候如果你使用上面的java -jar指令去执行mysql的驱动jar包就会出现上述不可执行的现象。(因为MySQL的jar包中没有主启动类,MySQL的java文件要交给外部使用者去调用)

​ 而我们的SpringBoot项目为什么能执行呢?其实是因为打包方式不一样。

​ 在SpringBoot工程的pom.xml中有下面这组配置,这组配置决定了打包出来的程序包是否可以执行。

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

spring boot用maven插件打包目录结构

image-20230625230048647

下面详细解释META-INF和org包含义

  1. META-INF

    包含pom.xml文件和MANIFEST.MF项目启动配置信息

    spring boot工程用maven插件打包后的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
    //指明了boot工程的引导类
    Start-Class: com.example.SSMPApplication
    Spring-Boot-Classes: BOOT-INF/classes/
    Spring-Boot-Lib: BOOT-INF/lib/
        
    Build-Jdk-Spec: 1.8
    Spring-Boot-Version: 2.6.11
    Created-By: Maven JAR Plugin 3.2.2
    //指明了boot工程启动时调用的主类
    Main-Class: org.springframework.boot.loader.JarLauncher
    
  2. org

    这个包里面主要包含了Main-Class:JarLauncher.class

  3. 这组配置的工作流程

    1. SpringBoot程序添加插件配置后会打出一个特殊的包,包含Spring框架部分功能,原始工程内容,原始工程依赖的jar包
    2. 首先读取MANIFEST.MF文件中的Main-Class属性,用来标记执行java -jar命令后运行的类
    3. JarLauncher类执行时会找到==Start-Class(boot引导类)==属性,也就是启动类类名
    4. 运行启动类时会运行当前工程的内容
    5. 运行当前工程时会使用依赖的jar包,从lib目录中查找

    就是说java -jar命令后不会直接去启动引导类,而是会去先启动类JarLauncher,再去启动引导类

  4. 总结

    看来SpringBoot打出来了包为了能够独立运行,将所有需要使用的资源全部都添加到了这个lib包里。这就是为什么这个jar包能独立运行的原因。

总结

  1. spring-boot-maven-plugin插件用于将当前程序打包成一个可以独立运行的程序包

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

​ 各位小伙伴在DOS环境下启动SpringBoot工程时,可能会遇到端口占用的问题。给大家一组命令,不用深入学习,备用吧。

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

SpringBoot项目快速启动(Linux版)

  • 运行jar包前,记得关闭Linux防火墙,否则拒绝http访问

YW-2.配置高级(了解一下可以通过外部修改配置即可)

image-20230329233550337

YW-2-1.临时属性设置

  • 临时属性添加位置:

    • 1.idea中手动添加
    • 2.运行时命令行传参
    • 3.自己手动设计执行类中args参数
    1. idea中手动添加

​ 目前我们的程序包打好了,可以发布了。但是程序包打好以后,里面的配置都已经是固定的了,比如配置了服务器的端口是8080。如果我要启动项目,发现当前我的服务器上已经有应用启动起来并且占用了8080端口,这个时候就尴尬了。难道要重新把打包好的程序修改一下吗?比如我要把打包好的程序启动端口改成80。

image-20211206095113771 image-20211206095524343 image-20211206095101581

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

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

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

java –jar springboot.jar –-server.port=80 --logging.level.root=debug
    
  1. 自己手动设计执行类中args参数
  • 加载参数的原理

image-20230329124701958

属性加载优先级

  • 常见优先级大小:临时属性 > 系统属性 > 配置文件
  • 属性加载冲突分析

​ 1. 优先级大小

​ 现在我们的程序配置受两个地方控制了,第一配置文件,第二临时属性。并且我们发现临时属性的加载优先级要高于配置文件的

image-20211206100859236

​ 第11条Command line arguments说的就是使用命令行临时参数。而这14种配置的顺序就是SpringBoot加载配置的顺序

  1. 属性读取冲突情况:

    分析:当出现属性冲突的时候,可按那张图从下向上排查得出结果

​ 在yaml中配置了user.name属性值,然后读取出来的时候居然不是自己的配置值,因为在系统属性中有一个属性叫做user.name,两个相互冲突了。而系统属性的加载优先顺序在上面这个列表中是5号,高于3号,所以SpringBoot最终会加载系统配置属性user.name。

总结

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

开发环境中使用临时属性

在idea中配置参数列表

image-20211206101947622

​ 做到这里其实可以产生一个思考了,如果对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) {
    String[] arg = new String[1];
    arg[0] = "--server.port=8082";
    SpringApplication.run(SSMPApplication.class, arg);
}

总结

  1. 启动SpringBoot程序时,可以选择是否使用命令行属性为SpringBoot程序传递启动属性

将多个配置属性放在一份文件里

YW-2-2.配置文件分类⭐️

  • 文件优先级覆盖
    1. file :config/application.yml 【最高】(包路径下,与jar包的同层目录下)
    2. file :application.yml
    3. classpath:config/application.yml (类路径下)
    4. classpath:application.yml 【最低】
  • 配置文件设置优先级的必要性:
  • 多个配置文件,优先用config文件夹的文件,然后再用resource里面的文件,配置取并集,出现同一样的属性,高优先级覆盖低优先级

  • 必要性,作用:

    image-20230625234910255

​ 在开发第一阶段用最低的配置级别,在开发第二阶段上线服务器后还需要改配置,这时就用第二级别的配置文件以此类推。

​ **级别1和2什么时候使用呢?**程序打包以后就要用这个级别了,管你程序里面配置写的是什么?我的级别高,可以轻松覆盖你,就不用考虑这些配置冲突的问题了。

总结

  1. 配置文件分为4种

  2. 多层级配置文件间的属性采用叠加并覆盖的形式作用于程序

YW-2-3.自定义配置文件:可以改名

自定义配置文件名字

​ 之前咱们做配置使用的配置文件都是application.yml,其实这个文件也是可以改名字的,这样方便维护。比如我2020年4月1日搞活动,走了一组配置,2020年5月1日活动取消,恢复原始配置,这个时候只需要重新更换一下配置文件就可以了。但是你总不能在原始配置文件上修改吧,不然搞完活动以后,活动的配置就留不下来了,不利于维护。

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

方式一:使用临时属性设置配置文件名,注意仅仅是名称,不要带扩展名

image-20211206105548238

方式二:使用临时属性设置配置文件路径,这个是全路径名

image-20211206105716450

​ 也可以设置加载多个配置文件

image-20211206105750285

​ 使用的属性一个是spring.config.name,另一个是spring.config.location,这个一定要区别清楚。

温馨提示

​ 我们现在研究的都是SpringBoot单体项目,就是单服务器版本。其实企业开发现在更多的是使用基于SpringCloud技术的多服务器项目。这种配置方式和我们现在学习的完全不一样,所有的服务器将不再设置自己的配置文件,而是通过配置中心获取配置,动态加载配置信息。为什么这样做?集中管理。

总结

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

YW-3.多环境开发⭐️(掌握一种)

  • 不同环境配置要分开写在不同的配置文件中,便于区分

    例如MySQL配置要单独写在一个文件中,然后交给统一的环境管理

​ 讲的内容距离线上开发越来越近了,下面说一说多环境开发问题。

​ 什么是多环境?其实就是说你的电脑上写的程序最终要放到别人的服务器上去运行。每个计算机环境不一样,这就是多环境。常见的多环境开发主要兼顾3种环境设置,开发环境——自己用的,测试环境——自己公司用的,生产环境——甲方爸爸用的。因为这是绝对不同的三台电脑,所以环境肯定有所不同,比如连接的数据库不一样,设置的访问端口不一样等等。

image-20211206110958819

YW-3-1.多环境开发(yaml单一文件版)

  • 其实就是设置多个配置环境,到时候随意切换

​ 那什么是多环境开发?就是针对不同的环境设置不同的配置属性即可。比如你自己开发时,配置你的端口如下:

server:
  port: 80

​ 如何想设计几组环境呢?中间使用三个减号分隔开

server:
  port: 80
---
server:
  port: 81

​ 那用哪一个呢?设置默认启动哪个就可以了

spring:
	config:
    	activate:
        	on-profile: pro #启动pro
---
spring:
	profiles: pro
server:
	port: 80
---
spring:
	profiles: dev
server:
	port: 81
---
spring:
	profiles: test
server:
	port: 82

总结

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

YW-3-2.多环境开发(yaml多文件版)⭐️

将原先在一个文件配置的不同环境,分成不同的配置文件

  • 主配置文件中写共有的配置,并指明开发环境

  • 分配置文件中指明不同开发环境下需要的配置

主配置文件

spring:
	profiles:
		active: pro		# 启动pro

环境配置文件

server:
	port: 80

​ 环境配置文件因为每一个都是配置自己的项,所以连名字都不用写里面了。那问题是如何区分这是哪一组配置呢?使用文件名区分。

application-pro.yaml

server:
	port: 80

application-dev.yaml

server:
	port: 81

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

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

  • 主配置文件中设置公共配置(全局)
  • 环境分类配置文件中常用于设置冲突属性(局部)
  • 这个就是子文件会对父文件的内容和配置继承和更改

总结

  1. 可以使用独立配置文件定义环境属性

  2. 独立配置文件便于线上系统维护更新并保障系统安全性

YW-3-3.多环境开发(properties多文件版)

​ SpringBoot最早期提供的配置文件格式是properties格式的,这种格式的多环境配置也了解一下吧。

主配置文件

spring.profiles.active=pro

环境配置文件

application-pro.properties

server.port=80

application-dev.properties

server.port=81

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

总结

  1. properties文件多环境配置仅支持多文件格式

YW-3-4.多环境开发独立配置文件书写技巧⭐️

  1. 解决问题:加载同一环境下不同的配置文件,将不同的配置文件合在一起

  2. 优先使用group语法开发

  3. 冲突处理:

    当主环境dev与其他环境有相同属性时,主环境属性生效(主环境配置优先);其他环境中有相同属性时,最后加载的环境属性生效

准备工作

​ 将所有的配置根据功能对配置文件中的信息进行拆分,并制作成独立的配置文件,命名规则如下

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

使用

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

spring:
	profiles:
    	active: dev						#相当于前缀
        include: devDB,devRedis,devMVC	#相当于后缀

​ 比较一下,现在相当于加载dev配置时,再加载对应的3组配置,从结构上就很清晰,用了什么,对应的名称是什么

改良

​ SpringBoot从2.4版开始使用group属性替代include属性,降低了配置书写量。简单说就是我先写好,你爱用哪个用哪个。

spring:
	profiles:
    	active: dev
        group:
        	"dev": devDB,devRedis,devMVC		#用group分开管理环境
      		"pro": proDB,proRedis,proMVC
      		"test": testDB,testRedis,testMVC

​ 现在再来看,如果切换dev到pro,只需要改一下是不是就结束了?完美!

YW-3-5.多环境开发控制⭐️

  • 出现意义:

    Maven是管理多环境的,boot是做开发的,所以我最终用什么配置环境(application.yml),我要听Maven的设置,因此有必要在Maven中配置我要启动哪一个环境,然后boot开发文件中直接引用就行

    说白了就是用maven来管理生产环境

  • 配置步骤:

    ①在pom.xml文件中配置profile标签

    ②在pom.xml文件中的build标签下配置resources标签

​ 多环境开发到这里基本上说完了,最后说一个冲突问题。就是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@

​ 上面的@属性名@就是读取maven中配置的属性值的语法格式

  • 需要在pom.xml中的build标签下添加,才能生效

    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <!--开启过滤,用指定的参数替换directory下的文件中的参数-->
            <filtering>true</filtering>
        </resource>
    </resources>
    

总结

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

YW-4.日志(了解)

​ 日志的主要作用:

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

YW-4-1.代码中使用日志工具记录日志

  1. 日志输出级别

  2. 日志输出级别控制:

步骤①:添加日志记录操作

@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";
    }
}

​ 上述代码中log对象就是用来记录日志的对象

步骤②设置日志输出级别⭐️

​ 日志设置好以后可以根据设置选择哪些参与记录。这里是根据日志的级别来设置的。日志的级别分为6种,分别是:

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

​ 一般情况下,开发时候使用DEBUG,上线后使用INFO,运维信息记录使用WARN即可。下面就设置一下日志级别:

​ 日志系统通常都提供了细粒度的控制来设置日志级别

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


logging:
	level:
    	root: debug

​ 还可以再设置更细粒度的控制

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

root也相当于一个组,一个大组

logging:
	# 设置日志组
    group:
    	# 自定义组名,设置当前组中所包含的包
        ebank: com.itheima.controller
        
    # 设置日志级别,root表示根节点,即整体应用日志级别
    level:
    	root: warn
        # 为对应组设置日志级别
        ebank: debug
        
    	# 为对包设置日志级别
        com.itheima.service: debug

​ 说白了就是总体设置一下,每个包设置一下,如果感觉设置的麻烦,就先把包分个组,对组设置,没了,就这些。

总结

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

教你一招:优化日志对象创建代码

导入lombok日志类之后,直接使用@Slf4j注解打印日志

@RestController
@RequestMapping("/books")
public class BookController extends BaseClass{
    private static final Logger log = LoggerFactory.getLogger(BookController.class);	//这一句可以不写了
}

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

总结

  1. 基于lombok提供的@Slf4j注解为类快速添加日志对象

YW-4-2.日志输出格式控制

​ 日志已经能够记录了,但是目前记录的格式是SpringBoot给我们提供的,如果想自定义控制就需要自己设置了。先分析一下当前日志的记录格式。

日志信息为各个类中调用log的相应方法打出来的方法

image-20211206123431222

​ 对于单条日志信息来说,日期,触发位置,记录信息是最核心的信息。级别用于做筛选过滤,PID与线程名用于做精准分析。了解这些信息后就可以DIY日志格式了。本课程不做详细的研究,有兴趣的小伙伴可以学习相关的知识。下面给出课程中模拟的官方日志模板的书写格式,便于大家学习。

logging:
	pattern:
    	console: "%d %clr(%p) --- [%16t] %clr(%-40.40c){cyan} : %m %n"

总结

  1. 日志输出格式设置规则

YW-4-3.日志文件⭐️

研究日志转存格式

​ 记录日志到文件中格式非常简单,设置日志文件名即可。

logging:
	file:
    	name: server.log

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

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

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

总结

  1. 日志记录到文件
  2. 日志文件格式设置

image-20230329165532889

运维实用篇完结

​ 运维实用篇到这里就要先告一段落了,为什么不说结束呢?因为运维篇中还有一些知识,但是现在讲解过于分散了。所以要把这些知识与开发实用篇的知识结合在一起讲,也是本课程的教学设计的体现。

​ 在整体运维实用篇中带着大家学习了4块内容,首先学习了如何运行SpringBoot程序,也就是程序的打包与运行,接下来对配置进行了升级学习,不再局限在配置文件中进行设置,通过临时属性,外部配置文件对项目的配置进行管控。在多环境开发中给大家介绍了多种多环境开发的格式,其实掌握一种即可,此外还给大家讲了多环境开发的一些技巧以及与maven的冲突解决方案。最后给大家介绍了日志系统,老实说日志这里讲的相当的潦草,因为大部分日志相关的知识都不应该在这门课中学习,这里只是告诉大家如何整合实用而已。

	name: server.log

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

```YAML
logging:
	logback:
    	rollingpolicy:
        	max-file-size: 3KB
            file-name-pattern: server.%d{yyyy-MM-dd}.%i.log

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

总结

  1. 日志记录到文件
  2. 日志文件格式设置

[外链图片转存中…(img-w19Wz0a7-1688197154374)]

运维实用篇完结

​ 运维实用篇到这里就要先告一段落了,为什么不说结束呢?因为运维篇中还有一些知识,但是现在讲解过于分散了。所以要把这些知识与开发实用篇的知识结合在一起讲,也是本课程的教学设计的体现。

​ 在整体运维实用篇中带着大家学习了4块内容,首先学习了如何运行SpringBoot程序,也就是程序的打包与运行,接下来对配置进行了升级学习,不再局限在配置文件中进行设置,通过临时属性,外部配置文件对项目的配置进行管控。在多环境开发中给大家介绍了多种多环境开发的格式,其实掌握一种即可,此外还给大家讲了多环境开发的一些技巧以及与maven的冲突解决方案。最后给大家介绍了日志系统,老实说日志这里讲的相当的潦草,因为大部分日志相关的知识都不应该在这门课中学习,这里只是告诉大家如何整合实用而已。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/36008.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt day3

完善文本编辑器 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QWidget>namespace Ui { class MainWindow; }class MainWindow : public QWidget {Q_OBJECTpublic:explicit MainWindow(QWidget *parent nullptr);~MainWindow(); public slots:void…

1.计算机是如何工作的(下)

文章目录 4.编程语言&#xff08;Program Language&#xff09;4.1程序&#xff08;Program&#xff09;4.2早期编程4.3编程语言发展 5.操作系统&#xff08;Operating System&#xff09;5.1操作系统的定位5.2什么是进程/任务&#xff08;Process/Task&#xff09;5.3进程控制…

es8.8 集群安装笔记

es8.8 集群安装笔记 配置集群第一步 修改配置文件 本次安装使用centos8 3节点安装&#xff1a; 192.168.182.142 192.168.182.143 192.168.182.144 官网 可以查看详细的安装&#xff0c;安装步骤比较简单 https://www.elastic.co/guide/en/elasticsearch/reference/8.8/rpm.htm…

Cannot find tomcat-9.0.0.M21/bin/setclasspath.sh

问题描述&#xff1a;将linux上的tomcat直接拷贝到以一个路径下&#xff0c;执行sh startup.sh 报错 解决&#xff1a;修改全局变量配置文件 1、vim /etc/profile &#xff08;主要修改如下图所标记的值 &#xff09; 2、source /etc/profile &#xff08;设置环境变量立即…

DynaSLAM 2018论文翻译

Dynaslam:动态场景下的跟踪、建图和图像修复 摘要-场景刚性假设是SLAM算法的典型特征。这种强假设限制了大多数视觉SLAM系统在人口稠密的现实环境中的使用&#xff0c;而这些环境是服务机器人或自动驾驶汽车等几个相关应用的目标。 在本文中&#xff0c;我们提出了一个基于ORB…

OpenCV 入门教程:膨胀和腐蚀操作

OpenCV 入门教程&#xff1a;膨胀和腐蚀操作 导语一、膨胀操作二、腐蚀操作三、示例应用3.1 图像增强3.2 边缘检测 总结 导语 膨胀和腐蚀是图像处理中常用的形态学操作&#xff0c;用于改变图像的形状和结构。在 OpenCV 中&#xff0c;膨胀和腐蚀是基于结构元素的像素操作&…

chatgpt生成pygame opengl实现旋转用图片填充的3d三角形

import pygame from pygame.locals import * from OpenGL.GL import * from OpenGL.GLU import *def draw_triangle():vertices ((0, 2, 0), # 顶点1(-2, -2, 0), # 顶点2(2, -2, 0) # 顶点3)tex_coords ((1, 2), # 顶点1的纹理坐标(1, 1), # 顶点2的纹理坐标(2, …

R语言绘图丨论文中最常用箱线图绘制教程,自动进行显著性检验和误差线标注

多组比较式箱线图 在科研论文绘图中&#xff0c;对于多组数据进行比较一般采用箱线图的方法&#xff0c;今天分享一下这个经典数据可视化方法&#xff0c;从零开始绘制一张带误差棒并自动计算显著性比较结果的箱线图。 前言&#xff1a;箱线图有什么优势&#xff1f; 数据分布…

mac电脑上,webm格式怎么转换成mp4?

mac电脑上&#xff0c;webm格式怎么转换成mp4&#xff1f;webm格式的视频也是最近几年也越来越多的&#xff0c;小编最近就不止一次的下载到过webm格式的视频&#xff0c;很多小伙伴肯定对它还并不是很了解&#xff0c;webm是由谷歌公司所提出以及开发出来的视频文件格式&#…

python实现语音识别(讯飞开放平台)

文章目录 讯飞平台使用python实现讯飞接口的语音识别第一步&#xff1a;导入需要的依赖库第二步&#xff1a;声明全局变量第三步&#xff1a;初始化讯飞接口对象第四步&#xff1a;收到websocket建立连接后的处理函数第五步&#xff1a;收到websocket消息的处理函数第六步&…

神经网络学习小记录74——Pytorch 设置随机种子Seed来保证训练结果唯一

神经网络学习小记录74——Pytorch 设置随机种子Seed来保证训练结果唯一 学习前言为什么每次训练结果不同什么是随机种子训练中设置随机种子 学习前言 好多同学每次训练结果不同&#xff0c;最大的指标可能会差到3-4%这样&#xff0c;这是因为随机种子没有设定导致的&#xff0…

删除链表的倒数第 N 个结点——力扣19

题目描述 法一&#xff09;计算链表长度 class Solution { public:int getLength(ListNode* head){int len0;while(head){len;head head->next;}return len;}ListNode* removeNthFromEnd(ListNode* head, int n) {int len getLength(head);ListNode* dummy new ListNode …

【Hello mysql】 mysql的约束

Mysql专栏&#xff1a;Mysql 本篇博客简介&#xff1a;介绍mysql的约束 mysql的约束 表的约束空属性默认值列描述zerofill主键自增长唯一键外键总结 表的约束 为什么要有约束&#xff1f; 我们在收集一些数据的时候会要求该数据必须存在 比如说像是国家在登记公民信息的时候身…

【Linux | Shell】Linux 安全系统 —— 用户、组、文件权限 - 阅读笔记

目录 一、Linux 的安全性1.1 /etc/passwd 文件1.2 /etc/shadow 文件1.3 添加新用户 —— useradd1.4 删除用户 —— userdel1.5 修改用户 —— usermod、passwd、chpasswd 二、使用 Linux 组2.1 /etc/group 文件2.2 创建新组 —— groupadd2.3 修改组 —— groupmod 三、理解文…

Swagger-Bootstrap-UI

Swagger-Bootstrap-UI 是一个为 Swagger 提供美观、易用的界面展示和增强功能的开源项目。它通过自定义样式和交互&#xff0c;提供了更好的文档展示和交互体验&#xff0c;包括美化的界面、接口测试工具、在线调试、文档导出等功能。 更高阶的有Knife4j,Knife4j是一个集Swagg…

免费 Selenium各大浏览器驱动【谷歌chrme、火狐Firefox、IE浏览器】

aardio群 625494397 废话不多说 直接开整&#xff01; 竟然还有脸收费 服了 下载对应版本的浏览器驱动 目标网址 应用场景 Selenium库涉及到 安装selenium库 pip install selenium-i https://mirrors.aliyun.com/pypi/simple/下载对应浏览器驱动 https://registry.npmmirror.c…

水电站运行数据3D可视化展示方便管理运维

水电站是现代能源体系中的重要组成部分&#xff0c;对于保障国家能源安全和经济发展具有重要的意义。然而&#xff0c;由于水电站的建设和管理涉及到大量的技术和专业知识&#xff0c;许多人对水电站的运行和维护存在许多疑惑和困惑。为了解决这些问题&#xff0c;我们引入了全…

TCP 重传机制 滑动窗口 流量控制 拥塞控制 学习总结!

大家好&#xff0c;我是三叔&#xff0c;很高兴这期又和大家见面了&#xff0c;一个奋斗在互联网的打工人。 这篇博客主要记录 tcp 的基础知识的学习总结相关内容&#xff01;备注&#xff1a;图片均来自作者&#xff1a;小林哥 tcp 的三大特性 tcp 大家都不陌生&#xff0c…

Work20230705

//main.c #include "uart4.h" extern void printf(const char *fmt, ...); void delay_ms(int ms) {int i,j;for(i 0; i < ms;i)for (j 0; j < 1800; j); }int main() {while(1){//将获取到的字符1发送到终端//hal_put_char(hal_get_char()1);hal_put_string…

chatGPT之100个例子-从体验到精通

简介 本博文演示了100个chatGPT在各行各业的使用例子,全部看完有助于培养chatGPT解决问题的思维。 在人工智能时代,智能软件并不会淘汰人类,淘汰人类的是会使用人工智能的人! 我们直接使用openAI官方chatGPT,生动演示了chatGPT的一些妙用! 请仔细看完,一定会有收获! 每…