
一、 SpringBoot项目的打包和启动【问题】在执行mvn package命令的时候会先执行test命令将在test中写的crud的操作都执行一遍此时会有测试数据的增加为了避免test操作可以跳过test执行命令1-1、springboot打包插件spring-boot-maven-plugin的作用使用springboot打包插件打出的jar包会比没有使用打包插件打出的jar包更大内容更多1、打包的文件结构的区别META-INF是 Java 的约定目录放在classpath下专门存放框架和 JVM 需要读取的配置元数据。Spring Boot 的自动配置、Java 的 SPI 机制、jar 包清单等都依赖这个目录。源文件里通常没有META-INF它是打包时自动生成的。META-INF/MANIFEST.MF是 Maven/Gradle 打包时自动创建的描述 jar 包信息。某些功能必须在源码里手动建META-INFSpring Boot 自动配置自定义 starter如果你想写一个自己的 starter就必须手动创建2、jar包描述文件MANFEST.MF的区别3、程序启动时发现端口被占用【注意】推荐使用进程pid号杀死进程因为进程名称可能会有多个1-2、临时属性的设置示例使用java -jar启动项目的时候临时想用另一个端口号启动application.yml中用的是80但是启动的时候想用8080端口1、启动命令行设置临时属性【注意】属性和application.yml中的key是一致的2、在idea中设置启动命令的临时属性设置Program arguments此时设置的参数可以在启动类中获取到所以出于安全的考虑可以在启动boot程序时断开读取外部临时配置对应的入口也就是去掉读取外部参数的形参二、Spring Boot 配置文件application2-1、多层级Spring Boot 配置文件加载优先级:若是做一些保密级别较高的项目数据库等配置信息保密配置文件可以保存在与project同文件夹的config文件夹中并且config文件夹没有访问权限。多层级的配置文件间的属性采用叠加并覆盖的形式作用于程序。2-2、自定义配置文件1、通过启动参数加载自定义的文件名无需写配置文件的扩展名2、通过通过启动参数加载指定文件路径下的配置文件【注意】1、这两种方式properties文件和yml格式的文件都是支持的。2、当指定了自定义配置文件的时候这时若是还有默认的application配置文件就不是叠加并覆盖的形式了而是就用指定的自定义的配置文件【备注】2-3、多环境开发下的配置文件1、多环境2、YAML 的多 profile 写法推荐如果你使用application.yml可以用---进行多环境分隔。properties格式的文件没有这种写法【注意】将每个环境中的公共配置放在最上面不同环境的配置写在不同环境中Spring Boot 版本标记环境的语法2.4 之前spring.profiles: dev2.4 及之后推荐spring.config.activate.on-profile: dev示例# 公共配置 激活声明 spring: application: name: my-app profiles: active: dev # ← ✅ 只激活 dev其他环境配置被忽略 --- # dev 环境配置 spring: config: activate: on-profile: dev # ← 标记这段配置属于 dev server: port: 8080 datasource: url: jdbc:mysql://localhost:3306/dev_db --- # test 环境配置 spring: config: activate: on-profile: test # ← 标记这段配置属于 test # 因为上面 active: dev这段不会加载 server: port: 8081 datasource: url: jdbc:mysql://192.168.1.10:3306/test_db --- # prod 环境配置 spring: config: activate: on-profile: prod # ← 标记这段配置属于 prod # 同样不会加载 server: port: 80 datasource: url: jdbc:mysql://10.0.0.5:3306/prod_db【注意】这种方式有信息暴露的风险因为所有的信息都在一个文件中。 所以可以写多个配置文件。3、多个配置文件的写法yml和properties格式的文件只是写法不同其余完全一致【注意】1、主配置文件中设置公共配置全局2、环境分类配置文件中常用于设置冲突属性局部4、多环境开发独立配置文件书写技巧1、使用maven占位符实际开发中maven可以有配置文件profilesspringboot也有配置文件profiles。因为springboot是依赖于maven的所以一定是maven先运行所以springboot可以读取maven的配置文件信息使用...读取。所以实际开发中有一个写法profile.name是Maven 占位符它通常出现在 Spring Boot 项目的配置文件中表示这个值将在构建mvn package时被 Maven 插件替换成实际的值。需要通过pom.xml中的配置在打包时注入实际的值。实际注入方式在pom.xml中定义properties profile.namedev/profile.name /properties或者通过build的resources插件替换变量build resources resource directorysrc/main/resources/directory filteringtrue/filtering !-- 开启占位符替换 -- /resource /resources /build结果:打包后application.yml中的spring: profiles: active: profile.name就会被替换成spring: profiles: active: dev# 默认打包激活 dev mvn package # application.yml 变成spring.profiles.active: dev # 显式激活生产环境 mvn package -P pro_env # application.yml 变成spring.profiles.active: pro【小提示】只有开启了资源文件的 filtering (filteringtrue/filtering) 才能让占位符生效。开发时如果没有打包IDEA 中运行时不会解析profile.name你可以临时写死或者通过启动参数指定-Dspring.profiles.activedev。【小结】图中 Maven Profile 的典型用法是通过资源过滤把spring.profiles.active的值注入到打包后的配置文件中两者是配合关系。【问题】在idea中切换默认激活的代码到其他的环境可能会不生效这是idea的缓存导致的。解决方式mvn compile手工编译。activation是否必须不是。不写activation你需要用-P xxx手动选择哪个 Maven profile。写了activeByDefaulttrue/activeByDefault在没传-P时默认用这个。维度Maven Profile图中方式Spring Bootapplication-{profile}.yml作用阶段构建时编译、打包运行时项目启动控制什么控制构建过程依赖、插件、资源过滤控制运行配置端口、数据库、日志级别谁读取MavenSpring Boot生效时机mvn package时java -jar启动时Maven Profile 能做Spring Boot 做不到profile iddev/id dependencies !-- dev 环境引入热部署工具 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-devtools/artifactId /dependency /dependencies /profile profile idprod/id build plugins !-- prod 环境跳过测试 -- plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-surefire-plugin/artifactId configuration skipTeststrue/skipTests /configuration /plugin /plugins /build /profile2、根据功能对配置文件拆分【写法一】include属性Spring Boot 里一个环境 profile 往往要管理多个功能模块的配置比如数据库DB缓存RedisWeb MVC如果全都写在application-dev.yml里会很臃肿。于是可以拆成多个小的配置文件application-devDB.ymlapplication-devRedis.ymlapplication-devMVC.ymlspring.profiles.include这个属性的作用是在激活某个环境时同时再加载额外的配置文件。含义是主 profile 是dev→ Spring Boot 会加载application-dev.yml。同时还会加载application-devDB.yml、application-devRedis.yml、application-devMVC.yml。多个配置文件会合并最后形成一个完整的环境配置。【注意】此时这些配置文件是有加载顺序的先顺序加载include中的配置文件最后加载active中的配置文件后面的文件信息覆盖前面的文件信息【写法二】group属性推荐YAML 中只有当 key 包含特殊字符时才需要引号。所以可以不加标准写法# application.yml spring: profiles: active: local # 只激活一个名字但实际加载一组配置 group: # 定义 local 组 dev mysql-local redis-local local: - dev - mysql-local - redis-local # 定义 prod 组 prod mysql-prod redis-prod sentinel prod: - prod - mysql-prod - redis-prod - sentinel效果# 激活 local实际加载application-dev.yml application-mysql-local.yml application-redis-local.yml java -jar app.jar --spring.profiles.activelocal # 激活 prod实际加载application-prod.yml application-mysql-prod.yml application-redis-prod.yml application-sentinel.yml java -jar app.jar --spring.profiles.activeprod与 include 的区别特性spring.profiles.groupspring.profiles.include定义位置application.yml的spring.profiles.group任意 profile 配置文件内激活方式spring.profiles.active组名激活某个 profile 后自动 include用途打包一组 profile 给一个名字某个 profile 激活时自动附带其他 profile【注意】加载顺序1. application.yml主配置包含 group 定义 └─ 发现 spring.profiles.active: dev └─ 发现 group.dev [devDB, devRedis, devMVC] 2. application-dev.ymlactive 指定的 profile └─ 加载 dev 环境的基础配置 3. application-devDB.ymlgroup 中的第1个 4. application-devRedis.ymlgroup 中的第2个 5. application-devMVC.ymlgroup 中的第3个 └─ 后面的覆盖前面的同名配置三、代码中使用日志记录工具3-1、日志级别TRACE运行堆栈信息使用率低DEBUG程序员调试代码使用INFO记录运维过程数据默认WARN记录运维过程报警数据ERROR记录错误堆栈信息FATAL灾难信息合并计入 ERROR3-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 注解推荐示例完整的配置和使用步骤1. 添加Lombok 依赖Maven项目在pom.xml里加上dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.32/version !-- 版本可根据需要调整 -- scopeprovided/scope /dependency2. 确认 IDE 已启用 Lombok 插件IntelliJ IDEA安装 Lombok 插件并在Preferences Build, Execution, Deployment Compiler Annotation Processors中开启Enable annotation processing。IDEA 的“注解处理”设置作用范围仅对 IDEA 自己的编译器和代码提示有效。开启后IDEA 在你写代码、点“运行”按钮时会调用注解处理器Annotation Processor帮你生成log、getter/setter等代码。这样你在 IDE 里就不会看到报红。对最终打包没有直接影响因为打包是 Maven/Gradle 调用javac编译而javac默认是支持注解处理器的只要你加了 Lombok 依赖javac会执行 Lombok 的处理逻辑。【注意】当注解处理开启时IDE 编译代码时会由 Lombok 的处理器在编译阶段生成一个private static final Logger log LoggerFactory.getLogger(当前类.class);3. 使用 Slf4j 注解然后在类上加Slf4jLombok 就会自动生成一个log日志对象类型是org.slf4j.Logger。4. 日志输出配置Spring Boot 默认使用Logback只要在application.properties或application.yml配置日志级别即可比如logging.level.rootINFO logging.level.com.example.demoDEBUG【总结】加 Lombok 依赖IDE 开启注解处理类上加Slf4j在代码里直接用log.info()等方法【回顾】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、文件记录日志方案1application.yml中配置缺点这种方式只能按大小滚动不能精确按天。这表示每天都会生成一个新日志文件%d{yyyy-MM-dd}在这一天中如果日志文件超过 3KB则会自动滚动新文件以.1.log,.2.log等结尾。方案2logback-spring.xml 配置在src/main/resources/下创建logback-spring.xml?xml version1.0 encodingUTF-8? configuration !-- 日志文件存放路径 -- property nameLOG_PATH valuelogs/ !-- 控制台输出 -- appender nameCONSOLE classch.qos.logback.core.ConsoleAppender encoder pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n/pattern /encoder /appender !-- 按天滚动的文件输出 -- appender nameFILE classch.qos.logback.core.rolling.RollingFileAppender !-- 当前正在写入的日志文件 -- file${LOG_PATH}/app.log/file !-- 滚动策略按时间 -- rollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy !-- 每天生成一个新文件文件名带日期 -- fileNamePattern${LOG_PATH}/app.%d{yyyy-MM-dd}.log/fileNamePattern !-- 保留 30 天的日志 -- maxHistory30/maxHistory !-- 总日志大小超过 10GB 时删除旧的 -- totalSizeCap10GB/totalSizeCap /rollingPolicy encoder pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n/pattern /encoder /appender !-- 根日志级别 -- root levelINFO appender-ref refCONSOLE/ appender-ref refFILE/ /root /configuration结果logs/ ├── app.log ← 今天的日志正在写入 ├── app.2026-07-17.log ← 昨天的日志 ├── app.2026-07-16.log ← 前天的日志 └── ...每天凌晨自动创建新文件旧文件按日期归档。