Spring 环境变量动态读取

我们的项目通常会发布在不同的系统、不同的受众环境提供外部或内部访问,如:内测、公测、生产环境、基于 WIN/LINUX等。发布至不同的环境,我们通常会配置不同的数据库账户密码、连接数、生成测试数据等。如果没有一套固定的机制自动配置,而在发布时手工修改,犯错率不仅很大,同时效率也很低。

程序员的优点是懒,缺点是不够懒。O(∩_∩)O哈哈哈~

以下分为 Spring App 和 Spring MVC 两种场景介绍,目的是打包前改一个变量,它能自动读取对应配置。如 env = prod

先创建一个 MyProperties 用于装载属性 key/value:

package com.caobug.demo.springenv;

/**
 * 属性
 * <p>
 * Created by caobug on 16/6/26.
 *
 * @author caobug
 * @since 1.7
 */
public class MyProperties {

    private String ipAddress;
    private String username;
    private String password;

    public String getIpAddress() {
        return ipAddress;
    }

    public void setIpAddress(String ipAddress) {
        this.ipAddress = ipAddress;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "MyProperties{" +
                "ipAddress='" + ipAddress + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

再创建配置文件spring-config.xml用于关联不同环境的配置。这里可以灵活变通为读取某个配置文件或直接注入。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <beans profile="developer">
        <bean id="myProperties" class="com.caobug.demo.springenv.MyProperties">
            <property name="username" value="a"/>
            <property name="ipAddress" value="192.168.1.2"/>
            <property name="password" value="123456"/>
        </bean>
    </beans>

    <beans profile="production">
        <bean id="myProperties" class="com.caobug.demo.springenv.MyProperties">
            <property name="username" value="b"/>
            <property name="ipAddress" value="192.168.1.3"/>
            <property name="password" value="654321"/>
        </bean>
    </beans>

</beans>

以上代码和平时的依赖注入没什么差别,仅仅是多了属性 profile="developer",他用于告诉 Spring 这需要特定环境才生效。这里还有一种写法是把以下片段:

<beans xmlns="http://www.springframework.org/schema/beans"

替换为:

<beans profile="developer" xmlns="http://www.springframework.org/schema/beans"

这样做之后将需要创建不同的XML文件,环境一多就不好维护了。

我们用JUNIT验证下我们的做法:

package com.caobug.demo.springenv;

import org.junit.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by caobug on 16/6/26.
 *
 * @author caobug
 * @since 1.7
 */
public class MyPropertiesTest {

    @Test(expected = NoSuchBeanDefinitionException.class)
    public void notFound() throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
        // ctx.getEnvironment().setActiveProfiles("developer");
        // ctx.refresh();
        MyProperties myProperties = ctx.getBean("myProperties", MyProperties.class);
        System.out.println("developer myProperties = " + myProperties);
    }

    @Test
    public void developer() throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
        ctx.getEnvironment().setActiveProfiles("developer");
        ctx.refresh();
        MyProperties myProperties = ctx.getBean("myProperties", MyProperties.class);
        System.out.println("developer myProperties = " + myProperties);
    }

    @Test
    public void production() throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
        ctx.getEnvironment().setActiveProfiles("production");
        ctx.refresh();
        MyProperties myProperties = ctx.getBean("myProperties", MyProperties.class);
        System.out.println("production myProperties = " + myProperties);
    }
}

我们需要特别注意的是,如果我们没有为ctx设定对应的环境(developer or production),或者有设定但未调用ctx.refresh();时,若尝试获取bean将会抛出NoSuchBeanDefinitionException异常,请参考以上notFound()测试方法。

楼上说:想RUN就RUN!不管了,我们再来看下 Spring MVC 中如何配置:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,991评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,971评论 6 342
  • spring官方文档:http://docs.spring.io/spring/docs/current/spri...
    牛马风情阅读 1,732评论 0 3
  • 1. 记得小学初中时文化课成绩都数一数二,就是体育是个犯愁的科目,尤其是仰卧起坐这个项目。每回考试都是非常勉强地在...
    小小洪阅读 579评论 1 2
  • 初三的表妹对我说:“姐,我有喜欢的男生了,但是我不知道怎么告诉他。”看着她羞赧又不知所措的脸,我拍了拍她的头:“用...
    肖婆阅读 293评论 0 1