起因

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

    挂接命令(mount) 首先,介绍一下挂接(mount)命令的使用方法,mount命令参数非常多,这里主要讲一下今天我们要用到的. 命令格式: mount [-t vfstype] [-o optio ...

  2. Oracle导入导出

    Oracle 10g 已经引入了数据泵(点击Data Dump)技术,这项技术和之前的exp/imp有哪些好处呢,简单的来说就是恢复和备份速度非常快: 在说明数据泵的使用方法之前,我们先来了解二者的区 ...

  3. 使用Logstash进行日志分析

    LogStash主要用于数据收集和分析方面,配合Elasticsearch,Kibana用起来很方便,安装教程google出来很多. 推荐阅读 Elasticsearch 权威指南 精通 Elasti ...

  4. [python]爬虫学习(三)糗事百科

    import requestsimport osfrom bs4 import BeautifulSoupimport timepage=2url='http://www.qiushibaike.co ...

  5. STM32 按键输入

    #include "stm32f10x.h"#include "key.h" //按键初始化函数void KEY_Init(void) { GPIO_InitT ...

  6. 不透明度opacity进阶

    一.opacity属性 1.opacity 习惯上说“透明度”,其实应该叫“不透明度”.opacity 意思:不透明,而背景色的默认值:transparent意思才是“透明的”.所以opacity用来 ...

  7. [No000083]文件与文件夹操作

    #region Folder option 文件夹操作 /// <summary> /// 指定目录是否存在 /// </summary> /// <param name ...

  8. knockout学习笔记10:demo

    前面已经介绍了ko的基本用法,结合官方文档,基本就可以实际应用了.本章作为ko学习的最后一篇,实现一个简单的demo.主要集中在ko,所以后台数据都是静态的.类似于博园,有一个个人文章的分类列表,一个 ...

  9. logback 常用配置详解<appender>

    logback 常用配置详解 <appender> <appender>: <appender>是<configuration>的子节点,是负责写日志的 ...

  10. .Net Core Logger 实现log写入本地文件系统

    .net core 自带一个基础的logger框架Microsoft.Extensions.Logging. 微软默认实现了Microsoft.Extensions.Logging.Console.d ...