Spring加载resource,classpath*:与classpath

2024-05-09 16:18

本文主要是介绍Spring加载resource,classpath*:与classpath,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Spring可以通过指定classpath*:与classpath:前缀加路径的方式从classpath加载文件,如bean的定义文件.classpath*:的出现是为了从多个jar文件中加载相同的文件.classpath:只能加载找到的第一个文件.

比如 resource1.jar中的package 'com.test.rs' 有一个 'jarAppcontext.xml' 文件,内容如下:

<bean name="ProcessorImplA" class="com.test.spring.di.ProcessorImplA" />

resource2.jar中的package 'com.test.rs' 也有一个 'jarAppcontext.xml' 文件,内容如下:

<bean id="ProcessorImplB" class="com.test.spring.di.ProcessorImplB" />

通过使用下面的代码则可以将两个jar包中的文件都加载进来

ApplicationContext ctx = new ClassPathXmlApplicationContext( "classpath*:com/test/rs/jarAppcontext.xml");

而如果写成下面的代码,就只能找到其中的一个xml文件(顺序取决于jar包的加载顺序)

ApplicationContext ctx = new ClassPathXmlApplicationContext( "classpath:com/test/rs/jarAppcontext.xml");

classpath*:的使用是为了多个component(最终发布成不同的jar包)并行开发,各自的bean定义文件按照一定的规则:package+filename,而使用这些component的调用者可以把这些文件都加载进来.

classpath*:的加载使用了classloader的 getResources() 方法,如果是在不同的J2EE服务器上运行,由于应用服务器提供自己的classloader实现,它们在处理jar文件时的行为也许会有所不同。 要测试classpath*: 是否有效,可以用classloader从classpath中的jar文件里加载文件来进行测试:getClass().getClassLoader().getResources("<someFileInsideTheJar>")。(上面的例子是在sun的jre中运行的状态)

从Spring的源码,在PathMatchingResourcePatternResolver类中,我们可以更清楚的了解其对的处理:如果是以classpath*开头,它会遍历classpath.

  1. protected Resource[] findAllClassPathResources(String location) throws IOException { 
  2.     String path = location; 
  3.     if (path.startsWith("/")) { 
  4.         path = path.substring(1); 
  5.     } 
  6.     Enumeration resourceUrls = getClassLoader().getResources(path); 
  7.     Set<Resource> result = new LinkedHashSet<Resource>(16); 
  8.     while (resourceUrls.hasMoreElements()) { 
  9.         URL url = (URL) resourceUrls.nextElement(); 
  10.         result.add(convertClassLoaderURL(url)); 
  11.     } 
  12.     return result.toArray(new Resource[result.size()]); 
<span style="background-color: rgb(255, 255, 255);">    protected Resource[] findAllClassPathResources(String location) throws IOException {String path = location;if (path.startsWith("/")) {path = path.substring(1);}Enumeration resourceUrls = getClassLoader().getResources(path);Set<Resource> result = new LinkedHashSet<Resource>(16);while (resourceUrls.hasMoreElements()) {URL url = (URL) resourceUrls.nextElement();result.add(convertClassLoaderURL(url));}return result.toArray(new Resource[result.size()]);}</span>

http://blog.csdn.net/kkdelta/article/details/5560210,简介了在JAVA里遍历classpath中读取找到的所有符合名称的文件.

 

另外在加载resource的时候,其他前缀的意义如下表所示:注意classpath*只能用与指定配置文件的路径,不能用在用于getResource的参数.如appContext.getResource("classpath*:conf/bfactoryCtx.xml")会异常的.

 

前缀 例子 说明

classpath:

classpath:com/myapp/config.xml

从classpath中加载。

file:

file:/data/config.xml

作为 URL 从文件系统中加载。

http:

http://myserver/logo.png

作为 URL 加载。

(none)

/data/config.xml

根据 ApplicationContext 进行判断。

从Spring的源码可以看出原因:如果是classpath:开头,从classpath加载,否则尝试URL,如果失败,调用 getResourceByPath

  1. public Resource getResource(String location) { 
  2.         Assert.notNull(location, "Location must not be null"); 
  3.         if (location.startsWith(CLASSPATH_URL_PREFIX)) { 
  4.             returnnew ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); 
  5.         } 
  6.         else { 
  7.             try { 
  8.                 // Try to parse the location as a URL...  
  9.                 URL url = new URL(location); 
  10.                 returnnew UrlResource(url); 
  11.             } 
  12.             catch (MalformedURLException ex) { 
  13.                 // No URL -> resolve as resource path.  
  14.                 return getResourceByPath(location); 
  15.             } 
  16.         } 
  17.     } 
<span style="background-color: rgb(255, 255, 255);">public Resource getResource(String location) {Assert.notNull(location, "Location must not be null");if (location.startsWith(CLASSPATH_URL_PREFIX)) {return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());}else {try {// Try to parse the location as a URL...URL url = new URL(location);return new UrlResource(url);}catch (MalformedURLException ex) {// No URL -> resolve as resource path.return getResourceByPath(location);}}}</span>

getResourceByPath会被不同ApplicationContext 实现覆盖.

如 GenericWebApplicationContext覆盖为如下:

  1. protected Resource getResourceByPath(String path) { 
  2.         returnnew ServletContextResource(this.servletContext, path); 
  3.     } 
  4.  
  5. 如 FileSystemXmlApplicationContext覆盖为如下: 
  6.  
  7. protected Resource getResourceByPath(String path) { 
  8.         if (path != null && path.startsWith("/")) { 
  9.             path = path.substring(1); 
  10.         } 
  11.         returnnew FileSystemResource(path); 
  12.     } 
<span style="background-color: rgb(255, 255, 255);">protected Resource getResourceByPath(String path) {return new ServletContextResource(this.servletContext, path);}如 FileSystemXmlApplicationContext覆盖为如下:protected Resource getResourceByPath(String path) {if (path != null && path.startsWith("/")) {path = path.substring(1);}return new FileSystemResource(path);}</span>

最终从文件加载的时候仍然是JAVA中常见的读取文件的方法:

 

如ClassPathResource得到inputstream的方法是利用class loader.

  1. public InputStream getInputStream() throws IOException { 
  2.     InputStream is; 
  3.     if (this.clazz != null) { 
  4.         is = this.clazz.getResourceAsStream(this.path); 
  5.     } 
<span style="background-color: rgb(255, 255, 255);">    public InputStream getInputStream() throws IOException {InputStream is;if (this.clazz != null) {is = this.clazz.getResourceAsStream(this.path);}</span>

如FileSystemResource得到inputstream的方法是利用FileInputStream.

 

    public InputStream getInputStream() throws IOException {        return new FileInputStream(this.file);     }

如ServletContextResource得到inputstream的方法是利用servletContext.getResourceAsStream.

  1. public InputStream getInputStream() throws IOException { 
  2.     InputStream is = this.servletContext.getResourceAsStream(this.path); 
  3.     if (is == null) { 
  4.         thrownew FileNotFoundException("Could not open " + getDescription()); 
  5.     } 
  6.     return is; 

这篇关于Spring加载resource,classpath*:与classpath的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/973878

相关文章

SpringBoot中HTTP连接池的配置与优化

《SpringBoot中HTTP连接池的配置与优化》这篇文章主要为大家详细介绍了SpringBoot中HTTP连接池的配置与优化的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、HTTP连接池的核心价值二、Spring Boot集成方案方案1:Apache HttpCl

Spring Boot项目打包和运行的操作方法

《SpringBoot项目打包和运行的操作方法》SpringBoot应用内嵌了Web服务器,所以基于SpringBoot开发的web应用也可以独立运行,无须部署到其他Web服务器中,下面以打包dem... 目录一、打包为JAR包并运行1.打包为可执行的 JAR 包2.运行 JAR 包二、打包为WAR包并运行

Java进行日期解析与格式化的实现代码

《Java进行日期解析与格式化的实现代码》使用Java搭配ApacheCommonsLang3和Natty库,可以实现灵活高效的日期解析与格式化,本文将通过相关示例为大家讲讲具体的实践操作,需要的可以... 目录一、背景二、依赖介绍1. Apache Commons Lang32. Natty三、核心实现代

Spring Boot 常用注解整理(最全收藏版)

《SpringBoot常用注解整理(最全收藏版)》本文系统整理了常用的Spring/SpringBoot注解,按照功能分类进行介绍,每个注解都会涵盖其含义、提供来源、应用场景以及代码示例,帮助开发... 目录Spring & Spring Boot 常用注解整理一、Spring Boot 核心注解二、Spr

SpringBoot实现接口数据加解密的三种实战方案

《SpringBoot实现接口数据加解密的三种实战方案》在金融支付、用户隐私信息传输等场景中,接口数据若以明文传输,极易被中间人攻击窃取,SpringBoot提供了多种优雅的加解密实现方案,本文将从原... 目录一、为什么需要接口数据加解密?二、核心加解密算法选择1. 对称加密(AES)2. 非对称加密(R

详解如何在SpringBoot控制器中处理用户数据

《详解如何在SpringBoot控制器中处理用户数据》在SpringBoot应用开发中,控制器(Controller)扮演着至关重要的角色,它负责接收用户请求、处理数据并返回响应,本文将深入浅出地讲解... 目录一、获取请求参数1.1 获取查询参数1.2 获取路径参数二、处理表单提交2.1 处理表单数据三、

java变量内存中存储的使用方式

《java变量内存中存储的使用方式》:本文主要介绍java变量内存中存储的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、变量的定义3、 变量的类型4、 变量的作用域5、 内存中的存储方式总结1、介绍在 Java 中,变量是用于存储程序中数据

如何合理管控Java语言的异常

《如何合理管控Java语言的异常》:本文主要介绍如何合理管控Java语言的异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、Thorwable类3、Error4、Exception类4.1、检查异常4.2、运行时异常5、处理方式5.1. 捕获异常

Spring Boot集成SLF4j从基础到高级实践(最新推荐)

《SpringBoot集成SLF4j从基础到高级实践(最新推荐)》SLF4j(SimpleLoggingFacadeforJava)是一个日志门面(Facade),不是具体的日志实现,这篇文章主要介... 目录一、日志框架概述与SLF4j简介1.1 为什么需要日志框架1.2 主流日志框架对比1.3 SLF4

Spring Boot集成Logback终极指南之从基础到高级配置实战指南

《SpringBoot集成Logback终极指南之从基础到高级配置实战指南》Logback是一个可靠、通用且快速的Java日志框架,作为Log4j的继承者,由Log4j创始人设计,:本文主要介绍... 目录一、Logback简介与Spring Boot集成基础1.1 Logback是什么?1.2 Sprin