起因

在实际开发过程中经常需要加载各种各样的配置文件..比如数据库的用户名密码,要加载的组件,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. Elixir 1.0 Release

    如期而至,9.9苹果产品发布会之后,紧接着在今天(教师节)我们终于等到了Elixir 1.0,苹果范儿的说法是:Now,Elixir 1.0 is here   注意:官网上的链接说明之类还没有更新过 ...

  2. 读《C#高级编程》第1章问题

    读<C#高级编程>第1章 .Net机构体系笔记 网红的话:爸爸说我将来会是一个牛逼的程序员,因为我有一个梦,虽然脑壳笨但是做事情很能坚持. 本章主要是了解.Net的结构,都是一些概念,并没 ...

  3. 表单中Readonly和Disabled的区别

    1.readonly是要锁定这个控件,通过在界面上无法修改他(但是通过javascript可以修改他). 2.disabled和readonly有相同的地方也是可以锁定这个控件用户不能改变他的值,但是 ...

  4. ajaxFileUpload插件

    关键词: $.ajaxFileUpLoad(); data status dataType 参考资料: http://www.cnblogs.com/kissdodog/archive/2012/12 ...

  5. Ubuntu 下ibus拼音输入法启用 (ubuntu 16.04

    Ubuntu 下ibus拼音输入法启用 我安装的是英文版的ubuntu 16.04,打开只带英文,并没有中文. 设置输入法为iBus 从system settings 进入language suppo ...

  6. 关于java的递归写法,经典的Fibonacci数的问题

    经典的Fibonacci数的问题 主要想展示一下迭代与递归,以及尾递归的三种写法,以及他们各自的时间性能. public class Fibonacci { /*迭代*/ public static ...

  7. 在Ubuntu Server 14.04中搭建FTP服务器(VMWare)

    自己搭建ftp服务器,方便主机与虚拟机中的Ubuntu传输文件. 选用的ftp软件为vsftpd. 1.命令行: sudo apt-get install vsftpd 2.安装完配置: vsftpd ...

  8. angular学习笔记(二十八-附1)-$resource中的资源的方法

    通过$resource获取到的资源,或者是通过$resource实例化的资源,资源本身就拥有了一些方法,$save,$delete,$remove,可以直接调用来保存该资源: 比如有一个$resour ...

  9. CentOS 配置MySQL允许远程登录

    Mysql为了安全性,在默认情况下用户只允许在本地登录,可是在有此情况下,还是需要使用用户进行远程连接,因此为了使其可以远程需要进行如下操作: 一.允许root用户在任何地方进行远程登录,并具有所有库 ...

  10. UOJ #221 【NOI2016】 循环之美

    题目链接:循环之美 这道题感觉非常优美--能有一个这么优美的题面和较高的思维难度真的不容易-- 为了表示方便,让我先讲一下两个符号.\([a]\)表示如果\(a\)为真,那么返回\(1\),否则返回\ ...