开发环境-测试环境-生产环境-配置自动切换N种办法

开发环境-测试环境-生产环境,各种环境的配置都不一样,比如数据库url,第三方支付url,还有一些其他的配置等等,还有代码的逻辑也是和环境有关,比如发短信和校验验证码在线下就没有必要,那么就要判断项目所处的环境,如果放到项目里面,每次发布到不同的环境都要改,改来改去挺麻烦,而且改掉一个项目就有问题,我总结了几种办法供大家参考,个个好使.

一, 如果只有数据库的配置需要改,那么可以使用JNDI,即在tomcat中配置DataSource, spring可以从JNDI中获取DataSource, 具体怎么配置就不说了,网上有很多.


二, 如果不只有数据库的配置,那就要用到下面说的办法了.
2.1, 使用环境变量
比如上面说的数据的配置, 我们一般是定义一个properties文件,内容基本都是这样:
jdbc.driverClass = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://xxx/xxx?useUnicode=true&characterEncoding=utf8
jdbc.user = xxx
jdbc.password = xxx
jdbc.maxPoolSize=50
jdbc.minPoolSize=10
jdbc.maxStatements=100
jdbc.testConnection=true


然后在spring的配置文件中指定这个文件,方式如下:
<context:property-placeholder location="classpath:config*.properties"/>


解决这种配置, 用环境变量比较好,改动很小.
只需要定义一个环境变量,比如变量名叫MY_CNF, 值为 D:/myconf, windows需要重启电脑才能获取到这个新增的环境变量,linux 执行一下source 命令就行了,能不能获取到可以用main方法打印一下System.getEnv("MY_CNF");试试看.
Eclipse中可以直接针对tomcat设置环境变量,不必重启电脑,设置方式:
services窗口中双击服务器-->open launch configuration -->Environment-->New 即可新增环境变量.

然后把properties文件复制到D:/myconf下,
spring中指定方式就不是classpath了,改成这样指定:
<context:property-placeholder location="file:${MY_CNF}/config.properties"/>


多个配置文件用逗号隔开,不支持*这种通配符
<context:property-placeholder location="file:${MY_CNF}/config.properties,file:${MY_CNF}/config-redis.properties"/>

项目中的配置文件就可以独立出去了


2.2 更暴力的办法
把配置文件放到某个目录下,比如D:/abc, 项目启动的时候,用脚本直接将D:/abc目录下的配置复制到tomcat/webapps/你的项目/WEB-INF/classes/对应配置文件目录 中, 替换项目中原有的配置文件.
怎么在启动前复制?直接改一下tomcat的startup.bat 或者startup.sh 即可, 在开头增加
cp -f D:/abc/xxx.propertiets /opt/tomcat/webapps/.....

项目中的配置文件就留本机开发的配置就行,这样本机开发不受影响.




上面几种办法已经可以解决问题了, 下面是些比较折腾的办法, 没搞过的可能看起来比较费劲.
2.3 使用maven中profile 标签和-P
如果项目是maven的,可以用这种方式.
在pom.xml中可以配置<profile>, 这个标签可以自己定义一些key 和value的属性,比如:
<profiles>
		<profile>
			<id>linux</id>
			<properties>
				<jrepath>${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/jre/lib/jce.jar</jrepath>
			</properties>
		</profile>
		
		
		<profile>
			<id>win</id>
			<properties>
				<jrepath>${JAVA_HOME}/jre/lib/rt.jar;${JAVA_HOME}/jre/lib/jce.jar</jrepath>
			</properties>
		</profile>
		
	</profiles>


其中<profiles> ,<profile>, <id>, <properties> 这几个标签的标签名是不能改的,
<properties> 下的 <jrepath> 这个标签就是自己写的, 标签名就是参数名, 标签体就是值.
上面代码的意思就是定义了两套名称叫<jrepath>的值, 一个id叫linux,一个id叫win,
然后在pom.xml的其他地方可以使用${jrepath}获取这个值,但是具体的是获取liunx下的值还是win下的值呢?这就要在执行maven命令时用-P参数指定<id>,
如: mvn package -Plinux


2.4 使用spring 的profile标签.
类似maven的profile标签,可以自己去看看,也是比较折腾,不爱用


2.5 redis方式
适合非项目启动参数和变动较少的常量数据
把参数通过后台编辑的方式(做一个管理页面)存到redis中.
简单点的,可以每次都从redis获取配置
优化点的, 就是避免每次都从redis获取,用redis的发布订阅模式, 项目启动时(Listener或者Filter或者spring的@PostConstrutor都行)把配置从redis中获取到缓存到本地内存中(如集合,常量等), 如果改动了redis数据, 项目订阅了此channel的消息, 然后从新从redis获取更新本机缓存,并且适合集群环境哦。


2.6 用System.setProperty的方式
用System.setProperty("key","value")的方式设置的值,在spring的配置文件或其他配置文件中都可以用${key}的方式获取值.
这样可以把配置文件全部放到自定义的环境变量对应的目录中,然后项目启动时读取配置文件,将配置信息通过System.setProperty的方式缓存起来, 然后spring配置中直接用${key}的方式.事例:
public class SysInitListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {

    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        String path = System.getenv("MY_CNF");
        try {
            InputStream in = new BufferedInputStream(new FileInputStream(path + "/xxx.properties"));
            Properties p = new Properties();
            p.load(in);

            /* //数据库
            System.setProperty("jdbc.driverClass", p.getProperty("jdbc.driverClass", "com.mysql.jdbc.Driver"));
            System.setProperty("jdbc.url", p.getProperty("jdbc.url", "线上地址"));
            System.setProperty("jdbc.user", p.getProperty("jdbc.user", "线上用户名"));
            System.setProperty("jdbc.password", p.getProperty("jdbc.password", "线上密码"));
                      
            //环境,默认生产环境
            SYSConstant.MS_ENV = EnvEnum.getByFlag(p.getProperty("env", "product"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}




spring 配置文件中用${key}的方式可以获取到值
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>


上述Listener中还有
 SYSConstant.MS_ENV = EnvEnum.getByFlag(p.getProperty("env", "product"));

这句就是从配置文件中获取一个叫env的值,赋值给项目中的一个常量, 这样在代码中判断这个常量就知道项目所处的环境了,有什么用?比如发短信或者校验短信验证码等在线下是没有必要的,那么就可以通过这个常量来判断业务逻辑


猜你喜欢

转载自18810098265.iteye.com/blog/2368914
今日推荐