您的位置:首页 > 编程语言 > Java开发

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

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

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

示例:

请注意db.properties和log4j.properties配置文件的位置,一定要放在resources文件夹下,配置遇到过大坑,在这一点上,文章最后会说明。




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文件中添加一下配置,这个配置的作用就是在不同环境下激活不同的配置,方法不止一种,下面提供其中一种可行的方式。

<!-- 通过profile决定env, 根据env来试用不同的过滤文件来处理resources中的properties文件 -->
<build>
<filters><!--获得过滤使用的源文件,即有实际数据的地方-->
<filter>src/main/resources/filters/filter-${env}.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
&l
d888
t;filtering>true</filtering><!--是否使用过滤器-->
<includes>
<include>
*.properties
</include>
</includes>
</resource>
</resources>
</build>
<!-- 打包的不同profile -->
<profiles>
<!-- 开发 -->
<profile>
<id>dev</id>
<properties>
<env>dev</env>
</properties>
<activation><!--默认激活-->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 生产 -->
<profile>
<id>product</id>
<properties>
<env>product</env>
</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/*.properties</value>
</list>
</property>
</bean>


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

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


写在最后,在配置的时候遇到一个巨坑,最后发现还是一个巨坑,下面将详细说明。

首先我的配置文件目录如下:



注意箭头标识的位置,我为了让文件目录更加清晰,在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


问题解决!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: