一、 SpringBoot项目的打包和启动

【问题】:在执行mvn package命令的时候,会先执行test命令,将在test中写的crud的操作都执行一遍,此时会有测试数据的增加,为了避免test操作,可以跳过test执行命令:

1-1、springboot打包插件:spring-boot-maven-plugin的作用
使用springboot打包插件打出的jar包会比没有使用打包插件打出的jar包更大,内容更多!

1、打包的文件结构的区别

2、jar包描述文件的区别

3、程序启动时,发现端口被占用

【注意】:
推荐使用进程pid号,杀死进程;因为,进程名称可能会有多个!
1-2、临时属性的设置
示例:使用java -jar启动项目的时候,临时想用另一个端口号启动
(application.yml中用的是80,但是启动的时候,想用8080端口)
1、启动命令行,设置临时属性

【注意】:
属性和application.yml中的key是一致的!
2、在idea中设置启动命令的临时属性:
设置:Program arguments

此时设置的参数,可以在启动类中获取到:


所以,出于安全的考虑,可以在启动boot程序时,断开读取外部临时配置对应的入口,也就是去掉读取外部参数的形参:

二、Spring Boot 配置文件application
2-1、多层级Spring Boot 配置文件加载优先级:


若是做一些保密级别较高的项目,数据库等配置信息保密,配置文件可以保存在与project同文件夹的config文件夹中,并且config文件夹没有访问权限。
多层级的配置文件间的属性采用叠加并覆盖的形式作用于程序。
2-2、自定义配置文件
1、通过启动参数加载自定义的文件名(无需写配置文件的扩展名)

2、通过通过启动参数加载指定文件路径下的配置文件

【注意】:
1、这两种方式:properties文件和yml格式的文件都是支持的。
2、当指定了自定义配置文件的时候,这时若是还有默认的application配置文件,就不是叠加并覆盖的形式了,而是就用指定的自定义的配置文件!
【备注】:

2-3、多环境开发下的配置文件
1、多环境

2、YAML 的多 profile 写法(推荐)
如果你使用
application.yml,可以用---进行多环境分隔。properties格式的文件,没有这种写法!!!

【注意】:
将每个环境中的公共配置,放在最上面,不同环境的配置,写在不同环境中!

【注意】:
这种方式有信息暴露的风险,因为所有的信息都在一个文件中。 所以,可以写多个配置文件。
3、多个配置文件的写法
yml和properties格式的文件,只是写法不同,其余完全一致


【注意】:
1、主配置文件中设置公共配置(全局)
2、环境分类配置文件中常用于设置冲突属性(局部)
4、多环境开发,独立配置文件,书写技巧:
(1)、使用maven占位符
实际开发中,maven可以有配置文件profiles,springboot也有配置文件profiles。
因为springboot是依赖于maven的,所以,一定是maven先运行,所以,springboot可以读取maven的配置文件信息,使用@...@读取。
所以,实际开发中,有一个写法:

@profile.name@ 是 Maven 占位符,它通常出现在 Spring Boot 项目的配置文件中,表示这个值将在构建(mvn package)时被 Maven 插件替换成实际的值。
需要通过 pom.xml 中的配置在打包时注入实际的值。
实际注入方式(在 pom.xml 中定义):
<properties>
<profile.name>dev</profile.name>
</properties>
或者通过 <build> 的 resources 插件替换变量:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering> <!-- 开启占位符替换 -->
</resource>
</resources>
</build>
结果:
打包后 application.yml 中的:
spring:
profiles:
active: '@profile.name@'
就会被替换成:
spring:
profiles:
active: dev
【小提示】:
只有开启了资源文件的 filtering (
<filtering>true</filtering>) 才能让占位符生效。开发时如果没有打包,IDEA 中运行时不会解析
@profile.name@,你可以临时写死或者通过启动参数指定-Dspring.profiles.active=dev。
【小结】:

【问题】:在idea中,切换默认激活的代码到其他的环境可能会不生效:
这是idea的缓存导致的。
解决方式:mvn compile,手工编译。
(2)、根据功能对配置文件拆分
【写法一】:include属性

【注意】:
此时这些配置文件是有加载顺序的!先顺序加载include中的配置文件,最后加载active中的配置文件(后面的文件信息覆盖前面的文件信息)
【写法二】:group属性(推荐)

【注意】:
此时,配置文件的加载顺序变化了,先加载active中的配置文件,再 顺序加载include中的配置文件(后面的文件信息覆盖前面的文件信息)
三、代码中使用日志记录工具

3-1、日志级别
- TRACE:运行堆栈信息,使用率低
- DEBUG:程序员调试代码使用
- INFO:记录运维过程数据(默认)
- WARN:记录运维过程报警数据
- ERROR:记录错误堆栈信息
- FATAL:灾难信息,合并计入 ERROR

3-2、设置某个包的日志级别:

3-3、设置分组,对某个分组设置日志级别(推荐)

3-4、快速创建日志对象
【问题】:每个类都要写一遍,很繁琐
private static final Logger logger = LoggerFactory.getLogger(CarController.class);
方式一:使用继承的方式
1、定义一个父类
public class MyLogUtils {
protected final Logger logger = LoggerFactory.getLogger(getClass());
}
2、让需要使用日志的类继承这个父类,即可。
方式二:使用 Lombok 的 @Slf4j 注解(推荐)

【回顾】:getClass()方法
getClass()是定义在java.lang.Object中的一个 实例方法,它在运行时返回的是 实际对象的类,而不是声明它的那个类。
举个例子:
public class LogSupport {
public void printClassName() {
System.out.println("class: " + getClass());
}
}
public class CarController extends LogSupport {
}
public class Demo {
public static void main(String[] args) {
LogSupport obj = new CarController();
obj.printClassName();
}
}
输出:
class: class CarController
你看,尽管 printClassName() 是写在 LogSupport 中的,但运行时调用的是 obj.getClass(),而 obj 的实际类型是 CarController,所以返回的是 CarController.class。
所以,你在 MyLogUtils 类中写了:
protected final Logger logger = LoggerFactory.getLogger(getClass());
谁继承了 LogSupport,调用 getClass() 得到的就是子类的 class 对象。
例如:
public class CarController extends LogSupport {
// logger 实际是 LoggerFactory.getLogger(CarController.class)
}
这就解决了每个类都写 LoggerFactory.getLogger(XXX.class) 的繁琐问题。
3-5、日志的输出格式

日志输出格式的控制

3-6、文件记录日志

这表示:
每天都会生成一个新日志文件(
%d{yyyy-MM-dd})在这一天中,如果日志文件 超过 3KB,则会 自动滚动,新文件以
.1.log,.2.log等结尾。
