【经典】springboot 配置文件统一管理

2023-10-27

背景

为实现快速搭建和开发,项目以Springboot框架搭建,springboot搭建的项目可以将项目直接打成jar包并运行,无需自己安装配置Tomcat或者其他服务器,是一种方便快捷的部署方式。

假设项目以最常规的方式打包成一个整体的jar包部署,即配置文件和第三方依赖包都包含在jar包里,就会有如下两个问题

问题一:项目运行过程中,要改动配置文件的话需要重新打包并部署。

问题二:多个第三方依赖包都相近的项目要部署在同一台服务器时,各自的jar包都包含了相同的第三方依赖包(假设项目jar包有100M,第三方依赖包可能就占用了99M),这样第三方依赖包冗余造成了服务器资源的浪费以及降低了项目部署的效率。

如果将各项目的配置文件、第三方依赖包都提取到jar包外统一管理,这样即提升了项目打包效率又节约了服务器的磁盘消耗,同时项目的运维也是非常方便的,改动了配置文件重启下服务就可以了,无需重新构建部署。

下面是具体的实现方案

1.1 配置文件统一管理

	- springboot核心配置文件
	- Springboot读取核心配置文件(application.properties)的优先级为
	- Jar包同级目录的config目录
	- Jar包同级目录
	- classPath(即resources目录)的config目录
	- classpath目录

上面是springboot默认去拿自己的核心配置文件的优先级,还有一种最高优先级的方式是项目启动时通过命令的方式指定项目加载核心配置文件,命令如下
java –jar -Dspring.config.location=xxx/xxx/xxxx.properties xxxx.jar

如果Spring Boot在优先级更高的位置找到了配置,那么它会无视优先级更低的配置

1.2 其他资源配置文件

上面描述的Springboot核心文件已经能够提取出jar包外进行管理了,但是还有其他一些业务上的配置文件,如数据源配置文件,公共资源定义配置文件(常量,FTP信息等),quartz定时器,日志等配置文件我们如何去提取出来并确保能在代码中引用到呢

我们知道Springboot项目可以通过注解方式来获取相关配置文件,所以我们也是通过注解方式让项目能够引用到jar包外部的配置文件的,如下图:
在这里插入图片描述

@PropertySource里面的value有两个值,第一个是classpath下config目录下的数据源配置文件,第二个则是根据spring.profiles.path动态获取的目录,spring.profiles.path是我们在核心文件自定义的一个配置项,它的值是我们配置文件统一管理的文件夹路径,后面的ignoreResourceNotFound=true则是设定假如根据前面一个路径没有找到相关配置文件,则根据第二个路径去找。

我们还可以直接根据路径,用FileSystemResource类去加载一个配置文件实例出来,如下图
在这里插入图片描述

原理类似,根据在核心文件自定义的统一配置目录的路径来加载配置文件

另外logback日志配置文件加载方式如下:
在这里插入图片描述

综上所述,我们梳理一下实现方案的思路

	- 在springboot核心文件里定义一个spring.profiles.path配置项,它的值指向我们所有配置文件统一放置的目录,包含核心文件自身也是放置在里面的

	- 代码或者配置文件里加载配置文件的地方也应该获取spring.profiles.path配置项来动态加载该路径下的配置文件

	- Pom.xml文件修改打包相关模块,将配置文件排除,这样我们打出的jar包是不含配置文件的,打包配置请参考文档节点3

	- 启动jar包时,通过命令指定加载的核心文件为spring.profiles.path下的核心文件
  1. 第三方依赖包统一管理

通常第三方jar包可以打进jar包里,也可以放在项目jar包同级目录下的lib目录,我们可以根据修改pom.xml打包配置来实现,请参考文档节点3打包配置

  1. 打包配置
<build>
		<resources>
			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.properties</include>
					<include>**/*.xml</include>
				</includes>
				<filtering>true</filtering>
			</resource>
			<resource>
				<directory>src/main/resources</directory>
				<!—打包时排除配置文件-->
                                <excludes>
					<exclude>**/*.properties</exclude>
					<exclude>**/*.xml</exclude>
					<exclude>**/*.yml</exclude>
				</excludes>
				<filtering>false</filtering>
			</resource>
		</resources>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<fork>true</fork>
					<skip>true</skip>
					<executable>
						C:/Program Files/Java/jdk1.8.0_161/bin/javac.exe
					</executable>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-jar-plugin</artifactId>
				<configuration>
					<archive>
						<manifest>
							<addClasspath>true</addClasspath>
							<classpathPrefix>lib/</classpathPrefix>
							<useUniqueVersions>false</useUniqueVersions>
							<mainClass>com.xrq.demo.Application</mainClass>
						</manifest>
						<manifestEntries>
							<Class-Path>./</Class-Path>
						</manifestEntries>
					</archive>
					<excludes>
						<exclude>*.properties</exclude>
						<exclude>*.yml</exclude>
						<exclude>*.xml</exclude>
						<exclude>config/**</exclude>
					</excludes>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
					<execution>
						<id>copy</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>
								${project.build.directory}/lib
							</outputDirectory>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>

改好pom.xml的build模块后,就可以通过mvn package 或者mvn install打出我们的jar包了

  1. 项目管理shell脚本编写
    自定义shell脚本,实现项目的启动,停止,状态,重启操作:
#!/bin/bash 
#这里可替换为你自己的执行程序,其他代码无需更改 
APP_NAME=demo1-0.0.1-SNAPSHOT.jar 
JVM="-server -Xms512m -Xmx512m -XX:PermSize=64M -XX:MaxNewSize=128m -XX:MaxPermSize=128m -Djava.awt.headless=true -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled"
APPFILE_PATH="-Dspring.config.location=/usr/local/demo/config/application-demo1.properties"
#使用说明,用来提示输入参数 
usage() { 
echo "Usage: sh 执行脚本.sh [start|stop|restart|status]" 
exit 1 
} 
#检查程序是否在运行 
is_exist(){ 
pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' ` 
#如果不存在返回1,存在返回0 
if [ -z "${pid}" ]; then 
return 1 
else 
return 0 
fi 
} 
#启动方法 
start(){ 
is_exist 
if [ $? -eq "0" ]; then 
echo "${APP_NAME} is already running. pid=${pid} ." 
else 
nohup java $JVM -jar $APPFILE_PATH $APP_NAME > /dev/null 2>&1 
fi
} 
#停止方法 
stop(){ 
is_exist 
if [ $? -eq "0" ]; then 
kill -9 $pid 
else 
echo "${APP_NAME} is not running" 
fi 
} 
#输出运行状态 
status(){ 
is_exist 
if [ $? -eq "0" ]; then 
echo "${APP_NAME} is running. Pid is ${pid}" 
else 
echo "${APP_NAME} is NOT running." 
fi 
} 
#重启 
restart(){ 
stop 
start 
} 
#根据输入参数,选择执行对应方法,不输入则执行使用说明 
case "$1" in 
"start") 
start 
;; 
"stop") 
stop 
;; 
"status") 
status 
;; 
"restart") 
restart 
;; 
*) 
usage 
;; 
esac
  1. 部署

linux服务器上新建个文件夹,将我们打好的项目jar包都丢进去,在jar包的同级目录新建config和lib文件夹,分别将配置文件和第三方依赖包丢进去,其结构如下图,*.sh为自己写的项目启动shell脚本

在这里插入图片描述

打开config内的springboot核心文件(如application-demo1.properties文件),

spring.profiles.path配置项改成当前配置文件所在的目录,假设为/usr/local/demo/config

打开*.sh脚本,修改APPFILE_PATH的值,如下

APPFILE_PATH="-Dspring.config.location=/usr/local/demo/config/application-demo1.properties"

  1. 项目管理

进入jar包所在目录执行下面命令

sh demo1.sh start 启动项目

sh demo1.sh stop 停止项目

sh demo1.sh restart重启项目

sh demo1.sh status项目状态


作者:xrq0508
来源:CSDN
原文:https://blog.csdn.net/xrq0508/article/details/80050119
版权声明:本文为博主原创文章,转载请附上博文链接!`

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【经典】springboot 配置文件统一管理 的相关文章

  • 不同帐户上的 Spring Boot、JmsListener 和 SQS 队列

    我正在尝试开发一个 Spring Boot 1 5 应用程序 该应用程序需要侦听来自两个不同 AWS 帐户的 SQS 队列 是否可以使用 JmsListener 注解创建监听器 我已检查权限是否正确 我可以使用 getQueueUrl 获取
  • 动态选择端口号?

    在 Java 中 我需要获取端口号以在同一程序的多个实例之间进行通信 现在 我可以简单地选择一些固定的数字并使用它 但我想知道是否有一种方法可以动态选择端口号 这样我就不必打扰我的用户设置端口号 这是我的一个想法 其工作原理如下 有一个固定
  • Pig Udf 显示结果

    我是 Pig 的新手 我用 Java 编写了一个 udf 并且包含了一个 System out println 其中的声明 我必须知道在 Pig 中运行时该语句在哪里打印 假设你的UDF 扩展了 EvalFunc 您可以使用从返回的 Log
  • java.lang.IllegalStateException:提交响应后无法调用 sendRedirect()

    这两天我一直在尝试找出问题所在 我在这里读到我应该在代码中添加一个返回 我做到了 但我仍然得到 java lang IllegalStateException Cannot call sendRedirect after the respo
  • 将 MOXy 设置为 JAXB 提供程序,而在同一包中没有属性文件

    我正在尝试使用 MOXy 作为我的 JAXB 提供程序 以便将内容编组 解组到 XML JSON 中 我创建了 jaxb properties 文件 内容如下 javax xml bind context factory org eclip
  • Eclipse Maven Spring 项目 - 错误

    I need help with an error which make me crazy I started to study Java EE and I am going through tutorial on youtube Ever
  • 当 OnFocusChangeListener 应用于包装的 EditText 时,TextInputLayout 没有动画

    不能比标题说得更清楚了 我有一个由文本输入布局包裹的 EditText 我试图在 EditText 失去焦点时触发一个事件 但是 一旦应用了事件侦听器 TextInputLayout 就不再对文本进行动画处理 它只是位于 editText
  • Java ResultSet 如何检查是否有结果

    结果集 http java sun com j2se 1 4 2 docs api java sql ResultSet html没有 hasNext 方法 我想检查 resultSet 是否有任何值 这是正确的方法吗 if resultS
  • 如何访问JAR文件中的Maven资源? [复制]

    这个问题在这里已经有答案了 我有一个使用 Maven 构建的 Java 应用程序 我有一个资源文件夹com pkg resources 我需要从中访问文件 例如directory txt 我一直在查看各种教程和其他答案 但似乎没有一个对我有
  • 不接受任何内容也不返回任何内容的函数接口[重复]

    这个问题在这里已经有答案了 JDK中是否有一个标准的函数式接口 不接受也不返回任何内容 我找不到一个 像下面这样 FunctionalInterface interface Action void execute 可运行怎么样 Functi
  • 专门针对 JSP 的测试驱动开发

    在理解 TDD 到底是什么之前 我就已经开始编写测试驱动的代码了 在没有实现的情况下调用函数和类可以帮助我以更快 更有效的方式理解和构建我的应用程序 所以我非常习惯编写代码 gt 编译它 gt 看到它失败 gt 通过构建其实现来修复它的过程
  • Cucumber 0.4.3 (cuke4duke) 与 java + maven gem 问题

    我最近开始为 Cucumber 安装一个示例项目 并尝试使用 maven java 运行它 我遵循了这个指南 http www goodercode com wp using cucumber tests with maven and ja
  • 最新的 Hibernate 和 Derby:无法建立 JDBC 连接

    我正在尝试创建一个使用 Hibernate 连接到 Derby 数据库的准系统项目 我正在使用 Hibernate 和 Derby 的最新版本 但我得到的是通用的Unable to make JDBC Connection error 这是
  • Android:无法使用 DbHelper 和 Contract 类将数据插入 SQLite

    public class Main2Activity extends AppCompatActivity private EditText editText1 editText2 editText3 editText4 private Bu
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java
  • 使用 CXF-RS 组件时,为什么我们使用 而不是普通的

    作为后续这个问题 https stackoverflow com questions 20598199 对于如何正确使用CXF RS组件我还是有点困惑 我很困惑为什么我们需要
  • 如何将双精度/浮点四舍五入为二进制精度?

    我正在编写对浮点数执行计算的代码的测试 不出所料 结果很少是准确的 我想在计算结果和预期结果之间设置一个容差 我已经证实 在实践中 使用双精度 在对最后两位有效小数进行四舍五入后 结果始终是正确的 但是usually四舍五入最后一位小数后
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • 如何防止在Spring Boot单元测试中执行import.sql

    我的类路径中有一个 import sql 文件 其中包含一些 INSERT 语句 当使用 profile devel 运行我的应用程序时 它的数据被加载到 postgres 数据库中 到目前为止一切正常 当使用测试配置文件执行测试时 imp
  • Java中super关键字的范围和使用

    为什么无法使用 super 关键字访问父类变量 使用以下代码 输出为 feline cougar c c class Feline public String type f public Feline System out print fe

随机推荐

  • 欧启标O老师STM32课程笔记(二)——蜂鸣器发声

    1 硬件原理 下图为蜂鸣器的电路图 分析这个电路 想让蜂鸣器发声 则需要有电流流过蜂鸣器 当BEEP 即PB8 为高电平时 三极管导通 电流流过蜂鸣器 蜂鸣器发声 反之 当BEEP 即PB8 为低电平时 三极管截止 蜂鸣器不发声 所以控制蜂
  • Rxjava参考文档

    https mcxiaoke gitbooks io rxdocs content operators Timer html
  • lua动态链接库(luaopen_*函数的使用)

    lua中使用c动态库 像luacjson 支持unicode luasocket 都是以动态链接库的形式在lua中使用的 至于怎么写这些动态链接库很少有教程说到 下面我就说说如何把c文件编译成动态库 首先 假设需要在lua中调用一个在c中实
  • 第二章 组合逻辑设计

    第二章 组合逻辑设计 1 卡诺图化简 1 1 必须是偶数项化简 因为卡诺图只有相邻格可以消除一个项 1 2 积之和形式的化简 消除相邻的1项 得到f 1 3 和之积形式的化简 消除相邻的0项 得到f 的积之和形式 然后再通过狄摩根定律转换成
  • python 按照行取平均值补齐缺失数据

    import pandas as pd 根据行来求平均值 def fill NAN filePath r E study python 0819 filled meter 500 csv df0 pd read csv filePath e
  • 线程池参数配置与Linux CPU

    1 线程池核心线程数配置 1 核心线程计算 计算密集型 cpu的个数 1 IO密集型 2 cpu个数 1 2 linux查看cpu核数 查看物理CPU个数 cat proc cpuinfo grep physical id sort uni
  • Educoder--Java高级特性 - 多线程基础(2)常用函数

    注意啦 这期的复制又恢复正常了 第一题 有三种原因可以导致线程不能运行 它们是 A 等待 B 阻塞 C 休眠 D 挂起及由于I O操作而阻塞 Java语言中提供了一个 线程 自动回收动态分配的内存 A 异步 B 消费者 C 守护 D 垃圾收
  • 字符串截取大全

    C 几个经常用到的字符串的截取 string str 123abc456 int i 3 1 取字符串的前i个字符 str str Substring 0 i or str str Remove i str Length i 2 去掉字符串
  • [C语言]猜数字

    本文章为c语言猜数字小游戏的教学 设计思路 目录 1 菜单的创建 2 猜数字的实现 3 完整代码 1 菜单的创建 先设计一个类似菜单的界面 供选择来实现游戏或退出 void menu printf n printf 猜数字 n printf
  • iTween基础之Look(使对象面朝指定位置)

    一 基础介绍 二 基础属性 原文地址 http blog csdn net dingkun520wy article details 50578142 一 基础介绍
  • 【Java基础】关于语言:编译型与解释型

    编译型 一 定义 使用专门的编译器 针对特定的平台 将高级语言源代码一次性的编译成可被该平台硬件执行的机器码 并包装成该平台所能识别的可执行性程序的格式 二 特点 程序执行前需要专门的一个编译过程 将源代码编译成机器语言 如 exe后缀的文
  • Python调用sort函数自定义排序函数

    当有一组比较复杂的对象需要进行排序时 我们的第一想法就是尽量利用已有的函数快速完成自己的排序需求 接触过c 的码友应该知道 在c 里若想利用已有的sort函数来完成复杂的排序 对运算符进行重载即可 好久没接触过c 里的概念 应该是这个叫法
  • java项目连接mysql卡死_我的Java连接数据库之后就卡住了 不能输出结果 到底是为什么呢?程序的功能是要完成一个地址的最大正向查...

    以下是基本的函数实现最重要的是第四个要实现街道的最大正向查找 ResultSetrs s executeQuery sql if rs next Stringpostaddress rs getString 1 Joutput setTex
  • 用Python开始机器学习(5:文本特征抽取与向量化)

    假设我们刚看完诺兰的大片 星际穿越 设想如何让机器来自动分析各位观众对电影的评价到底是 赞 positive 还是 踩 negative 呢 这类问题就属于情感分析问题 这类问题处理的第一步 就是将文本转换为特征 因此 这章我们只学习第一步
  • Hyperledger Fabric 应用实战(3)--配置文件core.yaml

    1 简介 core yaml主要是为Peer服务提供一些配置定义 当Peer节点启动时 会先从命令行获取参数 环境变量 和core yaml读取配置信息 通过docker去搭建一个Peer服务 命令行默认是不带参数的 主要通过docker
  • 考研 打赢这场信息站 上岸

    23考研已经结束了 新的考研马上开始 考研 是一个 持久战 也是一个 信息战 因为大多数同学都是自我监督 自我学习 所以经常出现想要摆烂 放弃的念头 意念坚定的同学只占一小部分 这个时候我们就要先在考研之前进行问题分析 这是一个非常非常重要
  • Spark Streaming入门

    什么是Spark Streaming 首先 什么是流 streaming 数据流是连续到达的无穷序列 流处理将不断流动的输入数据分成独立的单元进行处理 流处理是对流数据的低延迟处理和分析 Spark Streaming是Spark API核
  • openssl常用参数

    文章目录 前言 对称加密 标准语法 常用选项 应用示例 单向加密 标准语法 常用选项 应用示例 参考文档 前言 OpenSSL 是一个开源项目 可以实现 秘钥证书管理 对称加密和非对称加密 其主要由一下三个组件组成 openssl 多用途的
  • Synchronized与锁升级

    目录 1 先从阿里及其他大厂面试题说起 2 路线总纲 3 Synchronized的性能变化 4 Synchronized锁种类及升级步骤 4 1多线程访问情况 3种 4 2升级流程 4 3无锁 4 4偏向锁 4 5轻量级锁 4 6重量级锁
  • 【经典】springboot 配置文件统一管理

    背景 为实现快速搭建和开发 项目以Springboot框架搭建 springboot搭建的项目可以将项目直接打成jar包并运行 无需自己安装配置Tomcat或者其他服务器 是一种方便快捷的部署方式 假设项目以最常规的方式打包成一个整体的ja