Spring - Resources

Java 标准所提供的访问资源的类(如 java.net.URL、java.io.File 等)并不能很好地满足各种底层资源的访问需求,比如缺少从类路径或者 Web 容器的上下文中获取资源的操作类。

 

Resource 接口

Spring 提供了一个 Resource 接口,它为应用提供了更强的底层资源访问能力。Resource 接口主要的几个方法:

  • exists():返回一个 boolean 值,表示资源是否存在。
  • isOpen():返回一个 boolean 值,表示资源是否打开。
  • getInputStream():放资源对应的输入流。
  • getURL():如果底层资源可以表示成 URL,则返回对应的 URL对象。
  • getFile():如果底层资源对应一个文件,则返回对应的 File 对象。
  • getDescription():返回资源的描述。当处理资源出错时,资源的描述会用于错误信息的输出。一般来说,资源的描述是一个完全限定的文件名称或当前资源的真实 URL。

 

内置的 Resource 实现

UrlResource

UrlResource 封装了 java.net.URL,它使用户能够访问任何可以通过 URL 表示的资源,如 HTTP 资源、FTP 资源、文件系统资源等。例:

try {
    Resource resource = new UrlResource("http://example.com/");
    InputStream inStream = resource.getInputStream();
    String content = IOUtils.toString(inStream);
    System.out.println(content);
} catch (IOException e) {
    e.printStackTrace();
}

ClassPathResource

ClassPathResource 可以访问类路径下的资源,资源以相对于类路径的方式表示。例:

try {
    Resource resource = new ClassPathResource("conf/jdbc.properties");
    InputStream inStream = resource.getInputStream();
    String content = IOUtils.toString(inStream);
    System.out.println(content);
} catch (IOException e) {
    e.printStackTrace();
}

FileSystemResource

FileSystemResource 可以访问文件系统资源,资源以文件系统路径的方式表示。例:

try {
    Resource resource = new FileSystemResource("D:/test.txt");
    InputStream inStream = resource.getInputStream();
    String content = IOUtils.toString(inStream);
    System.out.println(content);
} catch (IOException e) {
    e.printStackTrace();
}

ServletContextResource

ServletContextResource 是为了访问 Web 容器上下文中的资源而提供的类,负责以相对于 Web 应用根目录的路径加载资源。它支持以流和 URL 的方式访问,在 WAR 解包的情况下,也可以通过 File 方式访问。该类还可以直接从 JAR 包中访问资源。例:

@WebServlet(name = "helloServlet", urlPatterns = { "/hello.png" })
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Resource resource = new ServletContextResource(req.getServletContext(), "/image/1.png");        
        InputStream inStream = resource.getInputStream();
        byte[] byteArray = IOUtils.toByteArray(inStream);
        resp.getOutputStream().write(byteArray);
    }
}

InputStreamResource

InputStreamResource 可以访问以输入流返回表示的资源。

ByteArrayResource

ByteArrayResource 可以访问以二进制数值表示的资源。

PathResource

PathResource 是 Spring 4.x 提供的读取资源文件的新类。Path 封装了 java.net.URL、java.nio.file.Path、文件系统资源,它使用户能够访问任何可以通过 URL、Path、系统文件路径表示的资源。

 

ResourceLoader

为了访问不同类型的资源,必须使用相对应的 Resource 实现类,这个是比较麻烦的。是否可以在不显示使用 Resource 实现类的情况下,仅通过资源地址的特殊标识就可以访问相应的资源呢?Spring 提供了一个强大的加载资源的机制,不但能够通过 “classpath:”、“file:” 等资源地址前缀识别不同的资源类型,还支持 Ant 风格带通配符的资源地址。

资源地址表达式

地址前缀 对应的资源类型 示例
 classpath: 从类路径中加载资源,classpath: 和 classpath:/ 是等价的,都是相对于类的根路径。资源文件可以在标准的系统文件中,也可在 JAR 或 ZIP 的类包中。  classpath:com/huey/hello/mapper/UserMapper.xml
 file: 从文件系统目录中装载资源,可采用绝对或相对路径。  file:/config/jdbc.properties
 http:// 从 HTTP 服务器中装载资源。  http://www.example.com/resource/beans.xml
 ftp:// 从 FTP 服务器中装载资源。  ftp://www.example.com/resource/beans.xml
 (none) 根据 ApplicationContext 的具体实现采用对应类型的 Resource。  com/huey/hello/config/beans.xml

与 “classpath:” 对应的还有一种 “classpath*:” 前缀。假设有多个 JAR 包或文件系统类路径都拥有一个相同的包名(如 com.huey)。“classpath:” 只会在第一个加载的 com.huey 包的类路径下查找,而 “classpath*:” 会扫描所以这些 JAR 包及类路径下出现的 com.huey 类路径。这对于分模块打包的应用非常有用。假设一个名为 helloworld 的应用共分成 3 个模块,一个模块对应一个配置文件,分别是 module1.xml、module2.xml 及 module3.xml,都放到 spring/config 目录下,每个模块单独打成 JAR 包。使用 “classpath*:spring/config/module*.xml” 可以成功加载这 3 个配置文件,而使用 “classpath:spring/config/module*.xml” 只会加载一个模块的配置文件。

Ant 风格的资源地址支持 3 种通配符:

  • ?:匹配文件名中的一个字符。
  • *:匹配文件名中的任意字符。
  • **:匹配任意层路径。

资源加载器

Spring 定义了一个资源加载的接口,并提供实现类。

ResourceLoader 接口仅有一个 getResource(String location) 方法,可以根据一个资源地址加载文件资源。不过,资源地址仅支持带资源类型前缀的表达式,不支持 Ant 更改的资源路径表达式。ResourcePatternResolver 扩展 ResourceLoader 接口,定义了一个新的接口方法 getResources(String locationPattern),该方法支持带资源类型前缀及 Ant 风格的资源路径表达式。PathMatchingResourcePatternResolver 是 Spring 提供的标准实现类。例:

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
    Resource[] resources = resolver.getResources("classpath*:conf/spring/*-beans.xml");
    for (Resource resource : resources) {
        System.out.println(resource.getDescription());
    }
} catch (IOException e) {
    e.printStackTrace();
}

ClassPathXmlApplicationContext & FileSystemXmlApplicationContext

Spring 里的所有应用上下文都实现了 ResourcePatternResolver 接口,因此,所有的应用上下文都可以通过 getResource()、getResources() 方法获取 Resource 实例。当通过 ClassPathXmlApplicationContext 实例调用 getResource 或 getResources 方法时,当没有显示指定资源前缀时,则将路径解析为类路径,同时返回的 Resource 实例是 ClasspathResource 类型;FileSystemXmlApplicationContext 则将路径解析为文件系统路径,返回的 Resource 实例是 FileSystemResource 类型。当以资源路径为参数构造 ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext 实例时也是一样的。

 

posted on 2018-02-03 18:52  huey2672  阅读(313)  评论(0编辑  收藏  举报