digdeep

凡是过去,皆是序幕。Read the fucking manual and source code.

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

classpath* 的可移植性问题,许多人都应该遇到过了。下面就是一个例子(使用的是spring4.1.5和mybatis3.2.8):

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
      <property name="dataSource" ref="dataSource" />
      <property name="configLocation" value="classpath*:config/mybatis-config-master.xml" />
      <property name="mapperLocations" value="classpath*:config/mappers/master/**/*.xml" />
    </bean>

上面的配置,在启动时报错:

Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/classpath*:config/mybatis-config-master.xml]
    at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:141)
    at org.mybatis.spring.SqlSessionFactoryBean.buildSqlSessionFactory(SqlSessionFactoryBean.java:358)
    at org.mybatis.spring.SqlSessionFactoryBean.afterPropertiesSet(SqlSessionFactoryBean.java:340)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1625)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1562)
    ... 49 more

spring在构造sqlSessionFactory这个bean时报错,原因是找不到配置文件:

Could not open ServletContext resource [/classpath*:config/mybatis-config-master.xml]

spring查找的路径是:/classpath*:config/mybatis-config-master.xml

而这个路径根本不是我们想要的,根本就是找错了地方。

但是我们配置文件给出的路径是:classpath*:config/mybatis-config-master.xml

我们将配置文件中下面的配置稍作修改,去掉classpath后面的 *

<property name="configLocation" value="classpath*:config/mybatis-config-master.xml" />

改为:

<property name="configLocation" value="classpath:config/mybatis-config-master.xml" />

之后,启动正常,没有报错。

原因

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.

不同的类加载器 classLoader 在处理 classpath* 时存在可移植性问题。如果在使用 classpath* 时报错,那么就应该去掉 * 直接使用classpath: ,如果还是报错,那么可以去掉classpath直接使用路径,在stackoverflow上有一个例子:http://stackoverflow.com/questions/6035464/could-not-open-servletcontext-resource

 

classpath* 和 classpath的区别

classpath* prefix specifies that all classpath resources that match the given name must be obtained (internally, this essentially happens via a ClassLoader.getResources(...) call), and then merged to form the final application context definition.

1)classpath* 它会搜索所有的 classpath,找到所有符合条件的文件,包括jar文件中的配置文件。而classpath不会到jar文件中去寻找。

2)classpath* 存在可移植性问题,遇到问题时,应该使用classpath.

3)其实一般情况下我们根本没有必要去使用classpath*,直接使用classpath就好了。

posted on 2015-05-10 22:10  digdeep  阅读(2479)  评论(0编辑  收藏  举报
不懂数据库和Web安全的架构师不是一个好的程序员。