基于tomcat与Spring的实现差异化配置方案
起因
在实际开发过程中经常需要加载各种各样的配置文件..比如数据库的用户名密码,要加载的组件,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就能找到这个资源.
然后我们来看一下资料..

从资料(文章及图片)中我们可以得知:
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的实现差异化配置方案的更多相关文章
- 利用maven实现差异化配置
回顾过去 生产环境,测试环境,开发环境在不同的环境下会有各种各样的配置,比如数据库链接地址,账户名,密码等等.不同环境下都需要配置,但是配置却又不同.以前分享过一篇文章,介绍了我之前A公司的差异化配置 ...
- Clusternet v0.5.0 重磅发布: 全面解决多集群应用分发的差异化配置难题
作者 徐迪,腾讯云容器技术专家. 汝英哲,腾讯云高级产品经理. 摘要 在做多集群应用分发的时候,经常会遇到以下的差异化问题,比如: 在分发的资源上全部打上统一的标签,比如 apps.my.compan ...
- Tomcat与WAS应用中间件差异化分析研究
--转载 http://blog.chinaunix.net/uid-25723371-id-5759072.html 目前我们在使用的基于JAVA的提供逻辑展现应用中间件有两种,一种是以商用软件WA ...
- .NET Core微服务之基于Steeltoe使用Spring Cloud Config统一管理配置
Tip: 此篇已加入.NET Core微服务基础系列文章索引 => Steeltoe目录快速导航: 1. 基于Steeltoe使用Spring Cloud Eureka 2. 基于Steelt ...
- 基于tomcat+spring+mysql搭建的个人博客
基于tomcat和spring开发的个人博客, 服务器是基于tomcat, 用了spring框架, web.xml的配置简单明了,我们只要配置MYSQL和用户过滤器等, 服务器的jsp就是负责VIEW ...
- Https系列之二:https的SSL证书在服务器端的部署,基于tomcat,spring boot
Https系列会在下面几篇文章中分别作介绍: 一:https的简单介绍及SSL证书的生成二:https的SSL证书在服务器端的部署,基于tomcat,spring boot三:让服务器同时支持http ...
- Android Gradle基于参数化配置实现差异化构建
一.背景: 项目中有一些特殊的需求,如个别渠道集成腾讯bugly,个别渠道集成易观统计,不同的渠道集成不同的推送策略(如Oppo渠道优先Opush推送),不同的渠道拥有不同的第三方登录集成等等.这些需 ...
- (转)iOS Wow体验 - 第三章 - 用户体验的差异化策略
本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第三章译文精选,其余章节将陆续放出.上一篇:Wow ...
- 改造继续之eclipse集成tomcat开发spring mvc项目配置一览
在上一篇的环境配置中,你还只能基于maven开发一个javase的项目,本篇来看如果开发一个web项目,所以还得配置一下tomcat和spring mvc. 一:Tomcat安装 在.net web开 ...
随机推荐
- 卡巴斯基2017激活教程_卡巴斯基2017用授权文件KEY激活的方法
原创:天诺时空 更新时间:2016-11-09 2016年9月7日,卡巴斯基2017版全新上市,卡巴斯基依旧为大家奉上满足您所有需求的安全软件产品,为不同年龄层.不同人群给予全方位保护,同时延续卡 ...
- [AR]高通Vuforia Getting Started
Vuforia Getting Started 简介 Vuforia创建增强现实应用程序是一个软件平台.开发人员可以轻松地将先进的计算机视觉功能添加到任何应用程序中,允许它识别图像和对象,或在现实 ...
- java util 下的concurrent包
------------------------------------------java util 下的concurrent包--------并发包--------------------.jav ...
- Selenium-java-Log4j环境搭建和
1 导入Log4j ,我这版本是1.2.17 自己选择版本 **别告诉我不会导入 2 Path 奶瓶 3 创建一个与src同目录文件 命名为 log4.properties 4 文件的内容是, ...
- 一个virtualbox开机即aborted的问题解决
问题: 之前想装最新的virtualbox版本,从官网下载了virtualbox最新的5点几的版本,使用sudo dpkg -i *.deb进行安装的. 然而,在virtualbox中启动了ubunt ...
- 解决IE浏览器文字上面放无内容的元素选不中的方法
<div class="md1"> <p><i>sdgsgereryeryery</i></p> <label c ...
- fail树
前置技能:AC自动机 假设我们有了一个AC自动机,然后在上面进行字符串匹配. 上面是一个有四个字符串的AC自动机(abcde.aacdf.cdf.cde),虚线是fail指针,实线是转移. 这是上一次 ...
- MySQL 用户登录密码和远程登录权限问题
1.mysql数据库,忘记root用户登录密码. 解决如下: a.重置密码 #/etc/init.d/mysqld stop #mysqld_safe --user=mysql --skip-gran ...
- C++ 模版
函数模版 #include <iostream> using namespace std; template<typename T> T add(T t1, T t2) { r ...
- Compiler Error Message: CS0016: Could not write to output file 回绝访问
Compiler Error Message: CS0016: Could not write to output file 'c:\Windows...dll' 拒绝访问 C:\Windows\Te ...