Maven项目部署WebLogic时遇java.io.FileNotFoundException问题求助
嗨,这种测试环境正常、一部署到WebLogic就找不到资源的问题我碰到过好多次了,核心就是两种环境的资源加载逻辑不一样,咱们一步步来解决:
先搞懂为啥测试能行,WebLogic不行
测试的时候(比如跑JUnit),项目的classpath直接包含了src/main/resources下的所有文件,类加载器能直接定位到;但打包成war/ear部署到WebLogic后,资源是被包在归档文件里的,不是磁盘上的独立文件,而且WebLogic的类加载机制有自己的优先级和规则,直接用文件路径找肯定会翻车。
一步步排查解决
1. 先确认资源有没有被正确打包
你得先解压打好的war包,看看WEB-INF/classes/certificates/keystore.jks这个路径下有没有文件。如果找不到,那是Maven打包的问题,得检查pom.xml里的资源配置,确保没把src/main/resources目录排除在外:
<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> </resource> </resources> </build>
这段配置会让Maven把src/main/resources下的所有文件都复制到war的WEB-INF/classes目录里,这是资源文件该待的地方。
2. 换正确的资源加载方式
别再用File类去读了!WebLogic里资源在war包内部,不是磁盘文件,File根本找不到。一定要用类加载器的流加载方式,这里有两个细节要注意:
- 用类加载器的话,路径别带开头的斜杠:
this.getClass().getClassLoader().getResourceAsStream("certificates/keystore.jks")这个写法是对的,因为类加载器是从classpath根目录开始找的; - 如果上面的方式返回null,试试用当前类的
getResourceAsStream,这时候路径要加开头的斜杠:this.getClass().getResourceAsStream("/certificates/keystore.jks"),这个斜杠代表从classpath根开始找,和类加载器的写法刚好相反。
3. 适配WebLogic的类加载特性
WebLogic的类加载器有层级结构,有时候会因为服务器类加载优先级高于应用,导致找不到应用里的资源。你可以试试:
- 在部署应用的时候,找到“类加载”配置选项,把类加载顺序改成“应用优先”(默认可能是“服务器优先”);
- 如果是在EJB或者其他容器组件里加载资源,偶尔会需要用
InitialContext来获取,但一般web应用里用类加载器就够了。
4. 加个调试代码找问题
你可以在代码里加一段调试逻辑,输出资源的实际加载路径,部署后看WebLogic的日志,就能知道是资源没打包还是路径写错了:
URL resourceUrl = this.getClass().getClassLoader().getResource("certificates/keystore.jks"); if (resourceUrl != null) { System.out.println("找到资源啦,路径是:" + resourceUrl.toString()); } else { System.out.println("资源没找到,检查打包和路径!"); }
最后再划个重点
核心就是:war包内的资源绝对不能用File类读取,必须用流的方式通过类加载器加载,同时确保资源被正确打包到WEB-INF/classes下,再根据WebLogic的类加载规则调整配置或者加载方式,问题基本就能解决啦。
内容的提问来源于stack exchange,提问作者Hendrien

