Spring配置中classpath与classpath*

18 篇文章 1 订阅

在使用spring写项目的时候,遇到一个很奇怪的问题。

看spring代码:整合mybatis

	<!-- 加载配置文件 -->
	<context:property-placeholder location="classpath*:config/db.properties" />
	<!-- sqlSessionfactory -->
	<bean id="sqlSessionFactory"
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 数据源 -->
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation"
			value="classpath*:config/sqlmapper.xml"></property>
		<!-- 加载mybatis配置文件 -->
		<property name="mapperLocations"
			value="classpath*:com/shop/mappering/*.xml" />
	</bean>

看报错信息:

严重: 异常将上下文初始化事件发送到类的侦听器实例.[org.springframework.web.context.ContextLoaderListener]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [config/spring-mybatis.xml]: Invocation of init method failed; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/classpath*:config/sqlmapper.xml]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:742)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
	at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:443)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:325)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4668)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5136)
	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.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:928)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:638)
	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.io.FileNotFoundException: Could not open ServletContext resource [/classpath*:config/sqlmapper.xml]
	at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:141)
	at org.mybatis.spring.SqlSessionFactoryBean.buildSqlSessionFactory(SqlSessionFactoryBean.java:407)
	at org.mybatis.spring.SqlSessionFactoryBean.afterPropertiesSet(SqlSessionFactoryBean.java:381)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
	... 42 more

他说文件找不到的错误,但是用classpath*配置他不是会去加载class路径以及jar包中的class路径去查找吗?

经过很长时间的百度,发现classpath*存在可移植性问题。

原因:

The wildcard classpath relies on the getResources() method of the underlying classloader. As most application servers nowadays supply their own classloader implementation, the behavior might differ especially when dealing with jar files. A simple test to check if classpath* works is to use the classloader to load a file from within a jar on the classpath: getClass().getClassLoader().getResources("<someFileInsideTheJar>"). Try this test with files that have the same name but are placed inside two different locations. In case an inappropriate result is returned, check the application server documentation for settings that might affect the classloader behavior.

说人话就是::

通配符类路径依赖于基础类加载器的getResources()方法。由于现在大多数应用服务器都提供自己的类加载器实现,因此在处理JAR文件时,行为可能会有所不同。检查ClassPath*是否有效的一个简单测试是使用ClassLoader从类路径上的jar中加载文件:getClass().getClassLoader().getResources(“<somefileinsidethejar>”)。尝试使用具有相同名称但位于两个不同位置的文件进行此测试。如果返回不适当的结果,请检查应用程序服务器文档中可能影响类加载器行为的设置。

这里不仅会有报找不到文件的错误,还有一个比较容易混淆你的错误就是

我配置db.properities里边写好连接数据库配置,当我加载的时候没报错,但是当${}这样去取值的时候就会报找不到这个值....

这个原理是啥我理解的也有局限性。上面说的只是一些踩坑经验,还望大家可以珍爱生命,远离bug,尽量别用classpath*

,尽量使用classpath。

classpath:只会去你class文件下去查找。位置从src下开始。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值