spring mvc 利用maven实现不同环境使用不同配置文件

在进行真实项目开发的时候,我们需要在不同的环境读取不同的配置信息,比如数据库连接信息,日志级别信息。我们可以用Maven来实现这一特性。

首先要有不同环境下的properties文件

示例:
请注意db.properties和log4j.properties配置文件的位置,一定要放在resources文件夹下,配置遇到过大坑,在这一点上,文章最后会说明。
spring mvc 利用maven实现不同环境使用不同配置文件_第1张图片
filter-dev.properties

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/dev?useUnicode=true&;characterEncoding=utf8&allowMultiQueries=true
db.user=dev
db.password=dev

filter-product.properties

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/product?useUnicode=true&;characterEncoding=utf8&allowMultiQueries=true
db.user=product
db.password=product

db.properties

db.driver=${db.driver}
db.url=${db.url}
db.username=${db.username}
db.password=${db.password}

接下来在项目的pom.xml文件中添加一下配置,这个配置的作用就是在不同环境下激活不同的配置,方法不止一种,下面提供其中一种可行的方式。


<build>
        <filters>
            <filter>src/main/resources/filters/filter-${env}.propertiesfilter>
        filters>
        <resources>
            <resource>
                <directory>src/main/resourcesdirectory>
                <filtering>falsefiltering>
            resource>
            <resource>
                <directory>src/main/resourcesdirectory>
                <filtering>truefiltering>
                <includes>
                    <include>
                        *.properties
                    include>
                includes>
            resource>
        resources>
    build>
    
    <profiles>
        
        <profile>
            <id>devid>
            <properties>
                <env>devenv>
            properties>
            <activation>
                <activeByDefault>trueactiveByDefault>
            activation>
        profile>
        
        <profile>
            <id>productid>
            <properties>
                <env>productenv>
            properties>
        profile>
    profiles>

以上配置了两种环境,dev和product环境,默认激活dev环境,可以用mvn clean package -Pproduct 命令激活product环境。

另外,在上面的示例当中,我们用到了${} 符来进行配置文件的读取,需要先将配置文件加载进来,现在有两种方式可以实现:
1. 使用属性占位符配置,PropertyPlaceholderConfigurer 这个类是继承自BeanFactoryPostProcessor,在BeanFactoryPostProcessor里面可以将配置中的属性进行统一的管理,在需要使用的时候直接使用占位符就可以。
在spring的配置文件applicationContext.xml里面进行以下配置。

<bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:/properties/*.propertiesvalue>
            list>
        property>
    bean>

2.原理同1一样,在spring的配置文件applicationContext.xml里面进行一下配置

<context:property-placeholder location="classpath:*.properties" />

写在最后,在配置的时候遇到一个巨坑,最后发现还是一个巨坑,下面将详细说明。
首先我的配置文件目录如下:
spring mvc 利用maven实现不同环境使用不同配置文件_第2张图片

注意箭头标识的位置,我为了让文件目录更加清晰,在resources文件夹下建了一个properties文件夹用来专门存储.properties文件。这是前提条件。在完成上述配置之后,我启动项目,然后出现以下报错:

[org.springframework.web.context.ContextLoader] - Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in class path resource [spring/applicationContext-database.xml]: Could not resolve placeholder 'db.url' in string value "${db.url}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'db.url' in string value "${db.url}"
    at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:211)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:180)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:155)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:265)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:162)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5110)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5633)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
三月 02, 2018 4:53:39 下午 org.apache.catalina.core.StandardContext startInternal
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1009)
严重: One or more listeners failed to start. Full details will be found in the appropriate container log file
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:985)
三月 02, 2018 4:53:39 下午 org.apache.catalina.core.StandardContext startInternal
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
严重: Context [] startup failed due to previous errors
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1899)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:618)
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:565)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1401)
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'db.url' in string value "${db.url}"
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:162)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:175)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.resolveStringValue(BeanDefinitionVisitor.java:282)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.resolveValue(BeanDefinitionVisitor.java:204)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitPropertyValues(BeanDefinitionVisitor.java:141)
    at org.springframework.beans.factory.config.BeanDefinitionVisitor.visitBeanDefinition(BeanDefinitionVisitor.java:82)
    at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:208)
    ... 54 more
[2018-03-02 04:53:39,462] Artifact springmvcProject:war exploded: Error during artifact deployment. See server log for details.

导致这个错误的直接原因是打包后的target/classes/db.properties配置文件中的属性占位符没有被替换,还是如下:

db.driver=${db.driver}
db.url=${db.url}
db.username=${db.username}
db.password=${db.password}

导致这个错误的根本原因是db.properties文件应该放置在resources文件夹下,而不是放在resources/properties文件夹下。

改过来之后,启动项目发现打包后db.properties配置文件如下:

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/dev?useUnicode=true&;characterEncoding=utf8&allowMultiQueries=true
db.user=dev
db.password=dev

问题解决!!!

你可能感兴趣的:(spring,mvc)