记一次mybatis的classpath踩坑记录


前情提要:

某日,M君外出办事,结果去早了,店家未开门。
见寒风凛冽,遂溜进一网吧。打开电脑欲大战机器人一把。
结果看到群内某男问了一个springmvc问题,M君按耐不住。欲解之,故有了下文。。。


问题描述:

环境:Spring+SpringMVC+Mybatis,Maven构建
异常:Install时,

[org.springframework.test.context.TestContextManager]Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@4a4038e2] to prepare test instance [sy.test.TestMybatis@6e030872]
java.lang.IllegalStateException: Failed to load ApplicationContext

起初一眼认定 ,测试用例TestMybatis里面的spring.xml路径配置错了。
于是你来我往聊了半天,没说出个所以然。再加上对maven不是非常熟悉,于是去看了看maven方面spring.xml配置文件的路径问题,发现应该是对的。
又问: service注解写了没啊?scan service的spring xml文件是哪个啊,有问有给进去啊?都没问题。
这下有点摸不着头脑了。

思索一小会儿,让其把完整异常发来。打开文件的瞬间一万个尼玛飞过。
大哥,你TM发异常能发完整不?
你可知道这会整死人不?
记一次mybatis的classpath踩坑记录_第1张图片

[org.springframework.test.context.TestContextManager]Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@4a4038e2] to prepare test instance [sy.test.TestMybatis@6e030872]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:103)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:73)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:313)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:146)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103)
    at com.sun.proxy.$Proxy0.invoke(Unknown Source)
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:145)
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:87)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void sy.service.UserServiceImpl.setUserMapper(sy.dao.UserMapper); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [sy.dao.UserMapper] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRoleMapper' defined in file [U:\Spring\testmybatis\target\classes\sy\dao\UserRoleMapper.class]: Cannot resolve reference to bean 'sqlSessionFactory' while setting bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [spring-mybatis.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.lang.String' to required type 'org.springframework.core.io.Resource[]' for property 'mapperLocations'; nested exception is java.lang.IllegalArgumentException: Could not resolve resource location pattern [classpath:sy/mapping/*.xml]: class path resource [sy/mapping/] cannot be resolved to URL because it does not exist

class path resource [sy/mapping/] cannot be resolved to URL because it does not exist
看完之后,立马认定还是路径不对,但是是sy/mapping/这个不对,而不是spring.xml,于是问这是什么玩意儿?
答:mybatis配置文件。

于是索要了项目结构图:
记一次mybatis的classpath踩坑记录_第2张图片

研究了半天,没发现啥错啊。
于是准备在网吧整个IDE编译看看。结果破网吧的网速不到500K。谁TM在下片啊。(吐槽下:自称网咖,却浓浓的烟味)

奈何还有急事在身,于是匆忙出了网吧,去办事了。


半小时后,回到办公室,要了份项目压缩包,就Happy的跑起来了。
研究了一会儿,没什么头绪,感觉什么都是对的。
思来想去,算了,换个路径,不是说maven推荐resources放资源文件嘛,那就把这些mapping丢resources源文件夹下。
Bingo!Success了。我了个去,百度了下,没这方面的情报。只有之后再研究研究了。
记一次mybatis的classpath踩坑记录_第3张图片


收获:

其实一直对classpath这个玩意儿一知半解,迷迷糊糊的。通过这次我对它认识更深了一步。

之前的印象:
在src目录下建个resources文件夹,丢配置文件.然后classpath:resources即可。
然后就是WEB-INF下的会自动被读取到。

现在:
看目录结构!source folder,和folder,还有package是有很大区别的!
按之前的理解,MybatisMapper下的mapper写法是:classpath:main/resources/MybatisMapper/*.xml
现在看来完全就是错误的,应该是classpath:MybatisMapper/*.xml
意思就是我们应该是按照源文件夹下的路径来写。(如果有错误或者不足欢迎指正,本人也是在学习)
(之后好好理解下源文件夹、文件夹、package的区别)

以及:
项目一定要按结构来划分,资源文件不要放在代码的package里面,那样是读不到的
(或者有方法能读到,但是肯定不如清晰的结构来得好)

其他:
classpath:/xxx 和 classpath:xxx是一样的
classpath:xxx 和 classpath*:xxx是不一样的,前者表示引入一个,后者表示引入多个。


其实我经常喜欢回答群里人问的问题,可能很多大神完全不屑于回答。但是对我这菜鸟来说,能在解答的过程中重新学习认识一遍。是一种很有效的学习/复习方法。而且从他人的代码/问题中能学习到很多我所没遇到的问题和知识。

想我当年高中意气风发时候,物理课从不听讲,书一直没翻过,只有等到妹子们来问我这个物理课代表课后题目的时候,我才临时抱佛脚,看一通,然后做出来给她们讲。现在看来,这方法到现在还适用啊!哈哈!所以说做题实践永远比死记硬背来的快也来的懂!

你可能感兴趣的:(Mybatis,Spring框架学习)