啟動tomcat,訪問一個web項目失敗,查看日志,發現異常信息:
18-Jul-2019 15:22:16.822 嚴重 [main] org.apache.catalina.core.StandardContext.listenerStart 異常將上下文初始化事件發送到類的偵聽器實例.[org.springframework.web.context.ContextLoaderListener]
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'dataSource' defined in class path resource [applicationContext.xml]: Could not resolve placeholder 'jdbc.driver' in string value "${jdbc.driver}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'jdbc.driver' in string value "${jdbc.driver}"
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:223)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:180)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:152)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:284)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:166)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:681)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:523)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4682)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5150)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:713)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:690)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1133)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1867)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:1045)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:429)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1576)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:309)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423)
at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:929)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1377)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1367)
at java.util.concurrent.FutureTask.run(Unknown Source)
at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at java.util.concurrent.AbstractExecutorService.submit(Unknown Source)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:902)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:932)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
at org.apache.catalina.startup.Catalina.start(Catalina.java:633)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492)
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'jdbc.driver' in string value "${jdbc.driver}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
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:172)
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:220)
... 50 more
網上找了類似的問題,有的是xml中名稱寫錯,有的是注釋掉了對應的變量名,但我這邊配置xml肯定是對的,在另一台電腦上(自己測試用的電腦)運行正常(兩台電腦,相同的操作系統win 2012 r2, 同樣版本及配置的tomcat,同樣的jre8,tomcat與jre8都是從相同的地方copy解壓的,web項目文件也一樣),但就是本電腦上(阿里雲的服務器)報錯,用的是druid數據庫連接池,看到有這樣一段(可配可不配)
<!--這一項可配可不配,如果不配置druid會根據url自動識別dbType,然后選擇相應的driverClassName-->
<property name="driverClassName" value="${jdbc.driver}"/>
試着將這段隱藏,重啟tomcat,訪問正常,不得其解。
以上為jdbc_sqlserver.properties內容:
jdbc.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver #jdbc:sqlserver://<server>:<port>;databaseName=AdventureWorks;user=<user>;password=<password> jdbc.url=jdbc:sqlserver://xxx.xxx.xxx.xxx;databaseName=MyTest jdbc.username=test jdbc.password=test #最大連接數 maxPoolSize=20 #最小連接數 minPoolSize=10 #連接超時時間 checkoutTimeout=60000 #失敗重連次數 acquireRetryAttempts=3
applicationContext.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--druid 此段摘自 https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE%E5%B1%9E%E6%80%A7%E5%88%97%E8%A1%A8-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--置這個屬性的意義在於,如果存在多個數據源,監控的時候可以通過名字來區分開來。如果沒有配置,將會生成一個名字,格式是:"DataSource-" + System.identityHashCode(this). 另外配置此屬性至少在1.0.5版本中是不起作用的,強行設置name會出錯-->
<!--<property name="name" value=""/>-->
<!--連接數據庫的url,不同數據庫不一樣-->
<property name="url" value="${jdbc.url}" />
<!--連接數據庫的用戶名-->
<property name="username" value="${jdbc.username}" />
<!--連接數據庫的密碼。如果你不希望密碼直接寫在配置文件中-->
<property name="password" value="${jdbc.password}" />
<!--這一項可配可不配,如果不配置druid會根據url自動識別dbType,然后選擇相應的driverClassName-->
<property name="driverClassName" value="${jdbc.driver}"/>
<!--初始化時建立物理連接的個數。初始化發生在顯示調用init方法,或者第一次getConnection時-->
<property name="initialSize" value="10" />
<!--最大連接池數量-->
<property name="maxActive" value="20" />
<!--最小連接池數量-->
<property name="minIdle" value="1" />
<!--獲取連接時最大等待時間,單位毫秒。配置了maxWait之后,缺省啟用公平鎖,並發效率會有所下降,如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖。-->
<property name="maxWait" value="60000" />
<!--是否緩存preparedStatement,也就是PSCache。PSCache對支持游標的數據庫性能提升巨大,比如說oracle。在mysql下建議關閉-->
<property name="poolPreparedStatements" value="true" />
<!--要啟用PSCache,必須配置大於0,當大於0時,poolPreparedStatements自動觸發修改為true。在Druid中,不會存在Oracle下PSCache占用內存過多的問題,可以把這個數值配置大一些,比如說100-->
<property name="maxOpenPreparedStatements" value="20" />
<!--用來檢測連接是否有效的sql,要求是一個查詢語句,常用select 'x'。如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會起作用。-->
<!--<property name="validationQuery" value="select 'x'" />-->
<!--單位:秒,檢測連接是否有效的超時時間。底層調用jdbc Statement對象的void setQueryTimeout(int seconds)方法-->
<!--<property name="validationQueryTimeout" value="3" />-->
<!--申請連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能-->
<property name="testOnBorrow" value="false" />
<!--歸還連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能。-->
<property name="testOnReturn" value="false" />
<!--建議配置為true,不影響性能,並且保證安全性。申請連接的時候檢測,如果空閑時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連接是否有效。-->
<property name="testWhileIdle" value="true" />
<!--連接池中的minIdle數量以內的連接,空閑時間超過minEvictableIdleTimeMillis,則會執行keepAlive操作-->
<property name="keepAlive" value="true" />
<!--有兩個含義:-->
<!--1) Destroy線程會檢測連接的間隔時間,如果連接空閑時間大於等於minEvictableIdleTimeMillis則關閉物理連接。-->
<!--2) testWhileIdle的判斷依據,詳細看testWhileIdle屬性的說明-->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!--連接保持空閑而不被驅逐的最小時間-->
<property name="minEvictableIdleTimeMillis" value="300000" />
<!--物理連接初始化的時候執行的sql-->
<!--<property name="connectionInitSqls" value="" />-->
<!--當數據庫拋出一些不可恢復的異常時,拋棄連接, 默認根據dbType自動識別-->
<!--<property name="exceptionSorter" value="" />-->
<!--屬性類型是字符串,通過別名的方式配置擴展插件,常用的插件有:-->
<!--監控統計用的filter:stat-->
<!--日志用的filter:log4j-->
<!--防御sql注入的filter:wall-->
<property name="filters" value="stat" />
<!--類型是List<com.alibaba.druid.filter.Filter>,如果同時配置了filters和proxyFilters,是組合關系,並非替換關系-->
<!--<property name="proxyFilters" value="" />-->
<!--屬性asyncInit是在建議的幫助文檔中寫的,但在實際介紹時沒有說明 https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE-->
<!--<property name="asyncInit" value="true" />-->
</bean>
<!--配合MyBatis-->
<bean id="vendorProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="SQL Server">sqlserver</prop>
<prop key="MySQL">mysql</prop>
</props>
</property>
</bean>
<bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
<property name="properties" ref="vendorProperties"/>
</bean>
<!-- 配置 SqlSessionFactory 對象,spring和MyBatis完美整合,不需要mybatis的配置映射文件-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入數據庫連接池-->
<property name="dataSource" ref="dataSource"/>
<!-- 配置 MyBaties 全局配置⽂件:mybatis-config.xml -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 掃描 model 包 使⽤別名 -->
<property name="typeAliasesPackage" value="com.zrensoft.model"/>
<property name="databaseIdProvider" ref="databaseIdProvider" />
<!-- 掃描 sql 配置⽂件:mapper 需要的 xml ⽂件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
<!-- 配置掃描 dao 接⼝包, 動態實現 dao 接⼝, 注⼊到 Spring 容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注⼊ sqlSessionFactory -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 給出需要掃描 dao 接⼝包 -->
<property name="basePackage" value="com.xxxx.dao"/>
</bean>
<!--spring-service-->
<!-- 掃描 service 包下所有使⽤注解的類型 -->
<context:component-scan base-package="com.xxxx.service"/>
<!-- 配置事務管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注⼊數據庫連接池 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<beans profile="sqlserver">
<context:property-placeholder location="classpath:jdbc_sqlserver.properties"/>
</beans>
<beans profile="mysql">
<context:property-placeholder location="classpath:jdbc_mysql.properties"/>
</beans>
</beans>
如有哪位發現問題是哪里,請告知,tks
