Spring 项目配置方式及优先级(案例)

发布时间:2026/5/26 16:25:24

Spring 项目配置方式及优先级(案例) Spring 项目配置方式及优先级案例Spring 项目配置方式及优先级一、配置方式分类1、配置文件方式application.properties传统的属性配置文件application.ymlYAML 格式的配置文件profile-specific 配置如application-dev.properties2、注解配置方式Configuration配置类定义PropertySource指定外部属性文件Value注入单个配置值ConfigurationProperties批量绑定配置属性3、环境变量配置系统环境变量操作系统级别的环境变量JVM 系统属性通过-D参数设置命令行参数启动时传递的--参数二、配置优先级顺序1、从高到低的优先级命令行参数(--server.port9000)JVM 系统属性(-Dserver.port9000)操作系统环境变量application-{profile}.properties/yml(当前激活 profile)application.properties/yml(默认配置文件)PropertySource 注解配置默认属性(通过 SpringApplication.setDefaultProperties 设置)2、Profile 配置优先级application-{profile}.properties优先于application.properties激活多个 profile 时后面的覆盖前面的配置三、配置加载时机1、启动阶段Environment 准备阶段系统属性和环境变量最先加载配置文件解析application.properties/yml 文件解析PropertySource 处理注解配置最后处理2、运行时配置RefreshScope支持配置热更新 (Spring Cloud Config)配置中心如 Nacos、Apollo 等外部配置中心四、最佳实践1、配置组织敏感配置使用环境变量或加密配置环境差异化使用 profile 配置不同环境配置验证使用Validated验证配置有效性2、优先级控制灵活覆盖通过优先级机制实现配置的灵活覆盖文档化维护配置项文档避免优先级冲突Spring 配置的优先级机制确保了配置的灵活性可以根据部署环境的不同通过适当的方式覆盖默认配置。五、项目实战1、value单个注入Service Slf4j RequiredArgsConstructor(onConstructor_ Lazy) public class PersonServiceImpl extends ServiceImpl PersonMapper, Person implements PersonService { private final OrganizationService organizationService; private static PersonService self; private final WechatPersonMapper wechatPersonMapper; Value(${outer.mechen.enable}) private boolean isMeiChen; Value(${outer.person-auto-create}) private boolean personAutoCreate; }2、批量属性注入微信支付配置常规方式直接标记为bean组件import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * description 微信支付配置商户 */ Data Component ConfigurationProperties(prefix payment.wx-mini-pay) public class WechatPayProperties { /** * 是否启用默认不启用避免证书密钥不齐全启动报错 */ private Boolean enable false ; /** * 小程序标识 */ private String appId; /** * 商户号 */ private String mchId; /** * 商户API私钥路径 */ private String mchKeyPath; /** * 商户证书序列号 */ private String mchCertNumber; /** * 商户V3 密钥 */ private String mchApiV3Key; /** * 小程序微信充值回调地址 */ private String notifyUrl; /** * 小程序微信充值退款回调地址 */ private String refundNotifyUrl; /** * 通用支付回调地址 */ private String payCallbackUrl; /** * 通用退款回调地址 */ private String refundCallbackUrl; /** * 验签模式wxPlatCert-微信平台证书默认wxPayPubKey-微信支付公钥。 * 二选一切换后以前旧的配置会失效需要重新在微信后台获取 */ private String verifySignMode wxPlatCert ; /** * 微信支付公钥ID */ private String publicKeyId; /** * 微信支付公钥路径 */ private String publicKeyPath; public boolean isVerifySignModeWxPlatCert () { return wxPlatCert .equals(verifySignMode); } public boolean isVerifySignModeWxPayPubKey () { return wxPayPubKey .equals(verifySignMode); } }支付宝配置import cn.hutool.core.io.FileUtil; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.annotation.PostConstruct; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.properties.ConfigurationProperties; import java.net.URL; import java.nio.charset.Charset; import java.util.Objects; Slf4j Data ConfigurationProperties(prefix alipay) public class AlipayProperties { /** * 是否启用 */ private boolean enable; /** * 运行模式 */ private String mode; /** * 服务商PID */ private String serverPid; /** * 商户PID */ private String mchPid; /** * 第三方应用ID提供当面付能力 */ private String thirdAppId; /** * 第三方应用私钥路径 */ private String thirdPrivateKeyPath; /** * 第三方支付宝公钥路径 */ private String thirdAlipayPublicKeyPath; /** * 第三方应用私钥 */ private String thirdPrivateKey; /** * 第三方应用支付宝公钥 */ private String thirdAlipayPublicKey; /** * 授权token用于代调用付款码兑换uid等接口 */ private String oauthToken; /** * 应用ID默认小程序暂不使用 */ private String appId; /** * 应用私钥路径 */ private String privateKeyPath; /** * 支付宝公钥路径 */ private String alipayPublicKeyPath; /** * 应用私钥 */ private String privateKey; /** * 支付宝公钥 */ private String alipayPublicKey; /** * 支卡通场景配置信息 */ private ZcardConfig zcardConfig; Data public static class ZcardConfig { Schema(description 支付宝分配的账号) private String accountId; Schema(description 场景码) private String sceneCode; Schema(description 子场景码) private String subSceneCode; Schema(description 产品码) private String productCode; } PostConstruct private void init () { if (!enable) { log.warn( 支付宝未启用 ); return ; } if ( partner .equals(mode)) { this .setThirdPrivateKey(thirdPrivateKeyPath); this .setThirdAlipayPublicKey(thirdAlipayPublicKeyPath); log.info( 支付宝服务商模式启动 ); } else { this .setPrivateKey(privateKeyPath); this .setAlipayPublicKey(alipayPublicKeyPath); log.info( 支付宝商户模式启动 ); } } private void setPrivateKey (String privateKeyPath) { try { URL resource AlipayProperties.class.getClassLoader().getResource(privateKeyPath); Objects.requireNonNull(resource); this .privateKey FileUtil.readString(resource, Charset.defaultCharset()); } catch (Exception e) { throw new RuntimeException ( 获取支付宝应用私钥失败 , e); } } private void setAlipayPublicKey (String alipayPublicKeyPath) { try { URL resource AlipayProperties.class.getClassLoader().getResource(alipayPublicKeyPath); Objects.requireNonNull(resource); this .alipayPublicKey FileUtil.readString(resource, Charset.defaultCharset()); } catch (Exception e) { throw new RuntimeException ( 获取支付宝应用公钥失败 , e); } } private void setThirdPrivateKey (String thirdPrivateKeyPath) { try { URL resource AlipayProperties.class.getClassLoader().getResource(thirdPrivateKeyPath); Objects.requireNonNull(resource); this .thirdPrivateKey FileUtil.readString(resource, Charset.defaultCharset()); } catch (Exception e) { throw new RuntimeException ( 获取支付宝第三方应用私钥失败 , e); } } private void setThirdAlipayPublicKey (String thirdAlipayPublicKeyPath) { try { URL resource AlipayProperties.class.getClassLoader().getResource(thirdAlipayPublicKeyPath); Objects.requireNonNull(resource); this .thirdAlipayPublicKey FileUtil.readString(resource, Charset.defaultCharset()); } catch (Exception e) { throw new RuntimeException ( 获取第三方支付宝公钥失败 , e); } } }按需启动import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.AlipayConfig; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.msg.AlipayMsgClient; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Slf4j Configuration EnableConfigurationProperties(AlipayProperties.class) //将配置注册为bean组件 public class AlipayServiceConfig { Bean public AlipayConfig alipayConfig (AlipayProperties properties) { // 引入配置bean return partner .equals(properties.getMode()) ? initAlipayConfigOfThirdApp(properties) : initAlipayConfigOfApp(properties); } Bean public AlipayClient defaultAlipayClient (AlipayConfig config) { try { return new DefaultAlipayClient (config); } catch (AlipayApiException e) { log.error( 支付宝默认客户端初始化失败 , e); throw new RuntimeException (e); } } // Bean // public AlipayMsgClient defaultAlipayMsgClient(AlipayProperties properties) { // 需要网页配置订阅消息 // try { // return getAlipayMsgClientOfApp(properties); // 该客户端需要设置消息处理器 // } catch (Exception e) { // log.error(支付宝默认消息客户端初始化失败, e); // throw new RuntimeException(e); // } // } /** * 初始化支付宝配置应用 * * param properties 配置 * return 支付宝应用配置 */ private AlipayConfig initAlipayConfigOfApp (AlipayProperties properties) { AlipayConfig alipayConfig new AlipayConfig (); alipayConfig.setServerUrl( https://openapi.alipay.com/gateway.do ); alipayConfig.setAppId(properties.getAppId()); alipayConfig.setPrivateKey(properties.getPrivateKey()); alipayConfig.setFormat( json ); alipayConfig.setAlipayPublicKey(properties.getAlipayPublicKey()); alipayConfig.setCharset( UTF-8 ); alipayConfig.setSignType( RSA2 ); return alipayConfig; } /** * 初始化支付宝配置第三方应用 * * param properties 配置 * return 第三方应用支付宝配置 */ private AlipayConfig initAlipayConfigOfThirdApp (AlipayProperties properties) { AlipayConfig alipayConfig new AlipayConfig (); alipayConfig.setServerUrl( https://openapi.alipay.com/gateway.do ); alipayConfig.setAppId(properties.getThirdAppId()); alipayConfig.setPrivateKey(properties.getThirdPrivateKey()); alipayConfig.setFormat( json ); alipayConfig.setAlipayPublicKey(properties.getThirdAlipayPublicKey()); alipayConfig.setCharset( UTF-8 ); alipayConfig.setSignType( RSA2 ); return alipayConfig; } private AlipayMsgClient getAlipayMsgClientOfApp (AlipayProperties properties) throws Exception { // 应用Id String appId properties.getAppId(); // 目标支付宝服务端地址线上环境为 openchannel.alipay.com String serverHost openchannel.alipay.com ; // 数据签名方式请与应用设置的默认签名方式保持一致 String signType RSA2 ; // 应用私钥 String appPrivateKey properties.getPrivateKey(); // 支付宝公钥 String alipayPublicKey properties.getAlipayPublicKey(); // 获取client对象一个appId对应一个实例 final AlipayMsgClient alipayMsgClient AlipayMsgClient.getInstance(appId); alipayMsgClient.setConnector(serverHost); alipayMsgClient.setSecurityConfig(signType, appPrivateKey, alipayPublicKey); return alipayMsgClient; } }3、条件控制bean好处是按需加载注意依赖该bean的也得注入为false或者配上一样的条件注解避免空指针异常Slf4j Service RequiredArgsConstructor ConditionalOnProperty(name outer.person-sync, havingValue true) public class JingBoPersonServiceImpl extends ServiceImpl PersonMapper, Person implements JingBoPersonService { private final PersonService personService; private static final ExecutorService EXECUTOR_SERVICE Executors.newFixedThreadPool( 3 ); }4、配置文件拆分设置默认配置按环境激活配置。使用运行脚本时指定环境参数test、prod等因为项目定制化所以也可以激活项目自定义配置。默认application.yml开发环境application-dev.yml测试环境application-test.yml生产环境application-prod.yml支付配置application-pay.yml自定义配置application-custom.ymlxx项目自定义配置application-XX.yml用于定制化项目脚本激活指定XX# 外部系统配置 outer: chuBang2: enable: false ip: token-url: ${outer.chuBan2g.ip}/uapws/rest/mwx/token/getToken.json userName: pwd: person-url: ${outer.chuBang2.ip}/uapws/rest/mwx/itf/getPsndoc.json org-url: ${outer.chuBang2.ip}/uapws/rest/mwx/itf/getOrg.json dept-url: ${outer.chuBang2.ip}/uapws/rest/mwx/itf/getDept.json # 设置当前短信供应商 sms: enable: false provider: TAO_LI taoli: sms: enable: false provider: TAO_LI balance-threshold: 50 max-retry-count: 3 appKey: appSecret: appCode: 1000 host: url: ${outer.taoli.sms.host}/sms/batch/v1 meichen: enable: false jingbo: person-auto-create: false lrh-card-pay: false person-sync: false通过后置将配置分类便于管理怎么引用呢在默认配置application.yml中引用激活配置文件spring: profiles: # 可以激活多个逗号隔开或者-的数组形式 active: dev include: - pay - custom - tenant - job5、配置文件优先级项目同级目录下config/application.yml项目同级目录下application.yml项目jar包内的配置文件优先级命令行参数 JVM变量 OS环境变量 配置文件 默认值处理方式同名则覆盖选择优先级最高的无则补充6、定制配置样例设置单独项目配置一般针对多项目多种支付配置使用开关比如各种支付配置默认不开启使用到才会启动湖南中车项目application-hnzc.yml# 服务器配置不同项目配置不同端口。一台云服务或物理机上面可能有多个项目 server: port: 9487 http-port: 9482 # 设置一个项目的基础可访问路径便于其他属于引用。常用 demo: base-url: https://ademo.waterqr.cn:10008 # 数据链接配置 spring: datasource: url: jdbc:mysql://127.0.0.1:4406/demo-hnzc?useUnicodetruecharacterEncodingUTF-8useSSLfalseallowMultiQueriestrue username: password: driver-class-name: com.mysql.cj.jdbc.Driver # 初始化大小最小最大 initialSize: 5 minIdle: 5 maxActive: 200 data: redis: host: 127.0 .0 .1 database: 0 port: 6379 password: wb2023.. timeout: 3000 redisson: watch-dog-timeout: 1000 file: upload-path: /home/ubuntu/demo/demo-hnzc/demo-java/upload ota-package-dir: ${file.upload-path}/ota-package/ ota-package-download-url: ${file.base-url}${server.servlet.context-path}/api/otaPackage/download/ base-url: ${demo.base-url} download-url: ${file.base-url}${server.servlet.context-path}/api/file/download/ view-url: ${file.base-url}${server.servlet.context-path}/api/file/view/ version-url: ${file.base-url}${server.servlet.context-path}/api/version/download/ # 微信小程序配置每个项目都不一样 wechat: mini-program: appid: xx appsecret: xx # 支付配置 payment: # 微信小程序支付 wx-mini-pay: # 是否启用 enable: false # 这些不开启的支付配置可以去掉因为默认就是关闭 alipay: enable: false citic-pay: enable: false # 银联支付 umspay: enable: false # 农行支付 abcpay: enable: false # 国通星驿支付 gtpay: enable: true url: # 服务器公网IP需要跟国通报备 server-ip: xx # 机构ID agent-id: xx7、运行脚本样例java脚本中-D参数在jar包之前--参数在jar包之后一个环境参数一个命令行参数关键激活参数--spring.profiles.activeprod,ephgzx这里的prod在jar包内而ephgzx在jar包外面优先级更高所以可以覆盖prod的配置这样的好处不需要重新打包仅仅修改配置文件重启项目即可if [ -f ./jar/demo-main-exec.jar ];then echo Step1:替换Jar文件 mv -f ./jar/demo-main-exec.jar ./demo-main-exec.jar else echo Step1:使用原Jar文件启动 fi echo Step2:关闭旧进程 sudo ps -ef|grep /demo-ephgzx/demo-java/demo-main-exec|grep -v grep|awk {system(echo Found and kill PID :$2;kill -9 $2)} # cd /home/ubuntu/demo-server/demo-java echo Step3:启动java程序 nohup java -jar -Xms128m -Xmx1500m /home/ubuntu/demo/demo-ephgzx/demo-java/demo-main-exec.jar --water.demo.mqtt.enabletrue --spring.profiles.activeprod,ephgzx --water.demo.thrid-party.dingding.enablefalse 21 if [[ -nolog $1 ]]; then echo Step4:跳过日志输出 else echo Step4:输出日志 sleep 3s tail -20f ./logs/water-logfile.log fi

相关新闻