• 基于tomcat与Spring的实现差异化配置方案


    起因

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

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

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

    1     <bean id="propertyPlaceholderConfigurer"
    2         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    3         <property name="locations">
    4             <list>
    5                 <value>classpath*:mysql.properties</value>
    6             </list>
    7         </property>
    8     </bean>
    1     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    2         destroy-method="close">
    3         <property name="driverClassName" value="${jdbc.driverClassName}" />
    4         <property name="url" value="${jdbc.url}" />
    5         <property name="username" value="${jdbc.username}" />
    6         <property name="password" value="${jdbc.password}" />
    7     </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方法.

     1     public Enumeration<URL> getResources(String name) throws IOException {
     2         Enumeration[] tmp = new Enumeration[2];
     3         if (parent != null) {
     4             tmp[0] = parent.getResources(name);
     5         } else {
     6             tmp[0] = getBootstrapResources(name);
     7         }
     8         tmp[1] = findResources(name);
     9 
    10         return new CompoundEnumeration<>(tmp);
    11     }

    我没有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也可以....只是我一直实验失败.....

  • 相关阅读:
    ubuntu 搜索文件方法(find命令)
    tomcat ip访问
    Linux下tomcat 的启动 关闭 kill
    Hibernate 之 使用
    tar 用法
    ubuntu下配置django+apache+mysql+mod_python+Python
    Windows Mobile Ping 命令实现(转)
    C#异步方法调用(四大方法详解)
    HTML基础(一):HTML简介
    windows2003系统的iis不能下载exe文件
  • 原文地址:https://www.cnblogs.com/abcwt112/p/5203348.html
Copyright © 2020-2023  润新知