起因

在实际开发过程中经常需要加载各种各样的配置文件..比如数据库的用户名密码,要加载的组件,bean等等..但是这种配置在各个环境中经常是不一样的....比如开发环境和测试环境,真实的生产环境..

这种配置不可能写死在代码里.很有可能会写在XML或者properties文件里..

这些文件可以在spring里去加载. 比如

     <bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:mysql.properties</value>
</list>
</property>
</bean>
     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>

比如不同环境下的数据库账号密码就可以通过配置不同的mysql.properties来解决.不同环境下需要加载的bean也可以通过这种方式解决.

然而这里有一个关键问题没有解决:

打包的结果是得到一个war包.mysql.properties会被打包到classpath的目录里去.

打包一般都是从一个环境里下统一打出来的.怎么让它把不同的配置打进去?

解决办法

其实我们并不需要把mysql.properties打包进去.可以通过设置maven的war plugin过滤掉mysql.properties.

既然不是打包进去的.那我们肯定要让Spring能够读取到这个配置.

直接将配置的路径写死在程序里显然不是一个好方法.因为不同机器上的mysql.properties差异文件的路径绝大多数都是不同的..

这里采用相对路径是个不错的办法...

我们先来看看Spring是怎么解析我们在XML中配置的路径(classpath*:mysql.properties)的.

在创建applicationContext的时候会根据xml的配置加载bean的配置

我们在PropertyPlaceholderConfigurer这个bean里配置了要加载mysql.properties.所以applicationContext会读取这个properties的地址.

在XML中这只是一个字符串...所以Spring还需要将它解析成具体的Resource才行....

这里用到了PathMatchingResourcePatternResolver类.

第323行可以发现怎么字符串mysql.properties这是一个相对路径,它要转化成绝对路径,再转化成Resource才行.转化成绝对路径最后靠的是ClassLoader的getResources方法.

     public Enumeration<URL> getResources(String name) throws IOException {
Enumeration[] tmp = new Enumeration[2];
if (parent != null) {
tmp[0] = parent.getResources(name);
} else {
tmp[0] = getBootstrapResources(name);
}
tmp[1] = findResources(name); return new CompoundEnumeration<>(tmp);
}

我没有tomcat的源码..但是从java的ClassLoader类中也可以看到会循环向上级ClassLoader查找资源,然后返回.

那么前面的问题就可以解决了..

我可以把mysql.properties放到这个webapp的classloader或者它父ClassLoader的classpath下.那Spring就能找到这个资源.

然后我们来看一下资料..

http://www.tuicool.com/articles/I3iqee

从资料(文章及图片)中我们可以得知:

webapp的classpath是WEB-INF下的lib和classes

我们的mysql.properties不可能放到这个里面.因为这个目录是被打到war包里面的...

那我们可以将mysql.properties放到sharedLoader或者commonLoader对应的classpath里即可...

那怎么得到那2种ClassLoader的classpath呢...

从 http://www.cnblogs.com/penzz/p/3241870.html 资料中我们可以得知.可以修改shared.loader去修改共享的class目录.

所以我们修改catalina.properties下的shared.loader.然后把mysql.properties放到shared.loader指定的目录下即可.

思考

配置当然也可以放到commonLoader的classpath下...但是显然是不需要的.因为Catalina服务器不需要用到我们的配置文件....

即使把配置放到shared.loader的classpath下也是多个web项目共享的...每个webapp项目都能够获取这个配置文件...

但是因为实际上可以通过一个tomcat只部署一个项目来解决这样的问题...多个webapp为了不相互干扰也不会用同1个tomcat启动的..不然1个webapp要重启tomcat也会影响其他webapp....所以sharedloader也不失为一种不错的解决办法...

当然最佳的解决办法还是让webappClassLoader能够读取到自己的配置文件.多个webappClassLoader不共享配置....但是貌似我的tomcat6不支持...不知道高版本的tomcat是不是有什么更好的方法....

总结

最后再来总结下实现差异化配置的方法(基于tomcat):

1.把差异化的东西放到特定的properties中(不一定真要是properties.只是它比较简单...或者把所有配置都放到XML中,但是把启动哪种配置的开关选项放到properties里),在打包的时候过滤掉这些文件.

2.设置catalina.properties.修改shared.loader的值为一个指定的目录

3.把差异化的properties文件放到shared.loader指定的目录下..

这样不同的环境下就可以有不同的配置文件了.而且每次打包也不需要关注那些差异的配置了..

另外不同的web容器肯定有不同的方法去设置classpath.不管怎么设置,只要让它能找到我们的配置文件就可以了..比如公司用的是weblogic...做法就比较简单粗暴...通过修改sh脚本直接在原本的classpath目录下再增加了一个classpath.......或许tomcat也可以....只是我一直实验失败.....

基于tomcat与Spring的实现差异化配置方案的更多相关文章

  1. 利用maven实现差异化配置

    回顾过去 生产环境,测试环境,开发环境在不同的环境下会有各种各样的配置,比如数据库链接地址,账户名,密码等等.不同环境下都需要配置,但是配置却又不同.以前分享过一篇文章,介绍了我之前A公司的差异化配置 ...

  2. Clusternet v0.5.0 重磅发布: 全面解决多集群应用分发的差异化配置难题

    作者 徐迪,腾讯云容器技术专家. 汝英哲,腾讯云高级产品经理. 摘要 在做多集群应用分发的时候,经常会遇到以下的差异化问题,比如: 在分发的资源上全部打上统一的标签,比如 apps.my.compan ...

  3. Tomcat与WAS应用中间件差异化分析研究

    --转载 http://blog.chinaunix.net/uid-25723371-id-5759072.html 目前我们在使用的基于JAVA的提供逻辑展现应用中间件有两种,一种是以商用软件WA ...

  4. .NET Core微服务之基于Steeltoe使用Spring Cloud Config统一管理配置

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 =>  Steeltoe目录快速导航: 1. 基于Steeltoe使用Spring Cloud Eureka 2. 基于Steelt ...

  5. 基于tomcat+spring+mysql搭建的个人博客

    基于tomcat和spring开发的个人博客, 服务器是基于tomcat, 用了spring框架, web.xml的配置简单明了,我们只要配置MYSQL和用户过滤器等, 服务器的jsp就是负责VIEW ...

  6. Https系列之二:https的SSL证书在服务器端的部署,基于tomcat,spring boot

    Https系列会在下面几篇文章中分别作介绍: 一:https的简单介绍及SSL证书的生成二:https的SSL证书在服务器端的部署,基于tomcat,spring boot三:让服务器同时支持http ...

  7. Android Gradle基于参数化配置实现差异化构建

    一.背景: 项目中有一些特殊的需求,如个别渠道集成腾讯bugly,个别渠道集成易观统计,不同的渠道集成不同的推送策略(如Oppo渠道优先Opush推送),不同的渠道拥有不同的第三方登录集成等等.这些需 ...

  8. (转)iOS Wow体验 - 第三章 - 用户体验的差异化策略

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第三章译文精选,其余章节将陆续放出.上一篇:Wow ...

  9. 改造继续之eclipse集成tomcat开发spring mvc项目配置一览

    在上一篇的环境配置中,你还只能基于maven开发一个javase的项目,本篇来看如果开发一个web项目,所以还得配置一下tomcat和spring mvc. 一:Tomcat安装 在.net web开 ...

随机推荐

  1. mariadb数据库忘记密码如何找回

    1.systemctl stop mariadb ==>停止mariadb数据库 2.mysqld_safe --skip-grant-tables & ==>进入单机模式 3.m ...

  2. SVN“验证位置时发生错误”的解决办法

    验证位置时发生错误:“org.tigris.subversion.javahl.ClientException...... 验证位置时发生错误:“org.tigris.subversion.javah ...

  3. Mac下安装GIT的坑

    先去 https://git-scm.com/download/mac 下载 GIT 客户端 双击安装,界面中有三个文件 接着双节 .pkg 文件,却提示无法安装 解决方式是按住 Control ,再 ...

  4. Leetcode 57: Insert Interval 让代码更好读, 更容易测试.

    阅读了几个博客, 决定写一个简易版本; 忙着做更多题, 没有时间多考虑优化代码, 所以, 就写一个试试运气. http://blog.csdn.net/kenden23/article/details ...

  5. 【原】让H5页面适配移动设备全家 - 设计师篇 - PPT

    上一篇文章<pageResponse - 让H5适配移动设备全家>中分享了一个小插件让一套H5页面适配几乎所有移动设备,得到了一些同学的推荐和认可,这里感谢大家的支持. 在此之前也在部门前 ...

  6. 【JS/CSS3】实现带预览图幻灯片效果~

    一.前期准备 1.1 案例分析 适用场景:单例布局1.2 方法论 V视图 HTML+CSS+调试C js实现控制流程D数据 优化扩展 二.代码 结构 <div class="slide ...

  7. [转载]fullPage.js中文api 配置参数~

    fullPage.js中文api 配置参数 选项 类型 默认值 说明 verticalCentered 字符串 true 内容是否垂直居中 resize 布尔值 false 字体是否随着窗口缩放而缩放 ...

  8. 最长不下降序列nlogn算法

    显然n方算法在比赛中是没有什么用的(不会这么容易就过的),所以nlogn的算法尤为重要. 分析: 开2个数组,一个a记原数,f[k]表示长度为f的不下降子序列末尾元素的最小值,tot表示当前已知的最长 ...

  9. Openjudge 1.13-23:区间内的真素数(每日一水)

    总时间限制:  1000ms 内存限制:  65536kB 描述 找出正整数 M 和 N 之间(N 不小于 M)的所有真素数.真素数的定义:如果一个正整数 P 为素数,且其反序也为素数,那么 P 就为 ...

  10. .NET跨平台之旅:探秘 dotnet run 如何运行 .NET Core 应用程序

    自从用 dotnet run 成功运行第一个 "Hello world" .NET Core 应用程序后,一直有个好奇心:dotnet run 究竟是如何运行一个 .NET Cor ...