目录

1       Resource简介

2       通过ResourceLoader获取资源

3       在bean中获取Resource的方式

1       Resource简介

在Spring内部,针对于资源文件有一个统一的接口Resource表示。其主要实现类有ClassPathResource、FileSystemResource、UrlResource、ByteArrayResource、ServletContextResource和InputStreamResource。Resource接口中主要定义有以下方法:

l  exists():用于判断对应的资源是否真的存在。

l  isReadable():用于判断对应资源的内容是否可读。需要注意的是当其结果为true的时候,其内容未必真的可读,但如果返回false,则其内容必定不可读。

l  isOpen():用于判断当前资源是否代表一个已打开的输入流,如果结果为true,则表示当前资源的输入流不可多次读取,而且在读取以后需要对它进行关闭,以防止内存泄露。该方法主要针对于InputStreamResource,实现类中只有它的返回结果为true,其他都为false。

l  getURL():返回当前资源对应的URL。如果当前资源不能解析为一个URL则会抛出异常。如ByteArrayResource就不能解析为一个URL。

l  getFile():返回当前资源对应的File。如果当前资源不能以绝对路径解析为一个File则会抛出异常。如ByteArrayResource就不能解析为一个File。

l  getInputStream():获取当前资源代表的输入流。除了InputStreamResource以外,其它Resource实现类每次调用getInputStream()方法都将返回一个全新的InputStream。

ClassPathResource可用来获取类路径下的资源文件。假设我们有一个资源文件test.txt在类路径下,我们就可以通过给定对应资源文件在类路径下的路径path来获取它,new ClassPathResource(“test.txt”)。

FileSystemResource可用来获取文件系统里面的资源。我们可以通过对应资源文件的文件路径来构建一个FileSystemResource。FileSystemResource还可以往对应的资源文件里面写内容,当然前提是当前资源文件是可写的,这可以通过其isWritable()方法来判断。FileSystemResource对外开放了对应资源文件的输出流,可以通过getOutputStream()方法获取到。

UrlResource可用来代表URL对应的资源,它对URL做了一个简单的封装。通过给定一个URL地址,我们就能构建一个UrlResource。

ByteArrayResource是针对于字节数组封装的资源,它的构建需要一个字节数组。

ServletContextResource是针对于ServletContext封装的资源,用于访问ServletContext环境下的资源。ServletContextResource持有一个ServletContext的引用,其底层是通过ServletContext的getResource()方法和getResourceAsStream()方法来获取资源的。

InputStreamResource是针对于输入流封装的资源,它的构建需要一个输入流。

  1. public class ResourceTest {
  2. /**
  3. * ClassPathResource可以用来获取类路径下的资源
  4. * @throws IOException
  5. */
  6. @Test
  7. public void testClassPath() throws IOException {
  8. Resource resource = new ClassPathResource("test.txt");
  9. String fileName = resource.getFilename();
  10. System.out.println(fileName);
  11. //    resource.getFile();   //获取资源对应的文件
  12. //    resource.getURL(); //获取资源对应的URL
  13. if (resource.isReadable()) {
  14. //每次都会打开一个新的流
  15. InputStream is = resource.getInputStream();
  16. this.printContent(is);
  17. }
  18. }
  19. /**
  20. * FileSystemResource可以用来获取文件系统里面的资源,对于FileSystemResource而言我们
  21. * 可以获取到其对应的输出流。
  22. * @throws IOException
  23. */
  24. @Test
  25. public void testFileSystem() throws IOException {
  26. FileSystemResource resource = new FileSystemResource("D:\\test.txt");
  27. if (resource.isReadable()) {
  28. //FileInputStream
  29. printContent(resource.getInputStream());
  30. }
  31. if (resource.isWritable()) {
  32. //每次都会获取到一个新的输出流
  33. OutputStream os = resource.getOutputStream();
  34. BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
  35. bw.write("你好,中国!");
  36. bw.flush();
  37. if (os != null) {
  38. os.close();
  39. }
  40. if (bw != null) {
  41. bw.close();
  42. }
  43. }
  44. }
  45. /**
  46. * 针对于URL进行封装的Resource,可用来从URL获取资源内容
  47. * @throws Exception
  48. */
  49. @Test
  50. public void testURL() throws Exception {
  51. UrlResource resource = new UrlResource("http://www.google.com.hk");
  52. if (resource.isReadable()) {
  53. //URLConnection对应的getInputStream()。
  54. printContent(resource.getInputStream());
  55. }
  56. }
  57. /**
  58. * 针对于字节数组封装的Resource,用来从字节数组获取资源内容
  59. * @throws IOException
  60. */
  61. @Test
  62. public void testByteArray() throws IOException {
  63. ByteArrayResource resource = new ByteArrayResource("Hello".getBytes());
  64. //ByteArrayInputStream()
  65. printContent(resource.getInputStream());
  66. }
  67. /**
  68. * 针对于输入流的Resource,其getInputStream()方法只能被调用一次。
  69. * @throws Exception
  70. */
  71. @Test
  72. public void testInputStream() throws Exception {
  73. InputStream is = new FileInputStream("D:\\test.txt");
  74. InputStreamResource resource = new InputStreamResource(is);
  75. //对于InputStreamResource而言,其getInputStream()方法只能调用一次,继续调用将抛出异常。
  76. InputStream target = resource.getInputStream();   //返回的就是构件时的那个InputStream
  77. //is将在printContent方法里面进行关闭
  78. printContent(target);
  79. }
  80. /**
  81. * 输出输入流的内容
  82. * @param is
  83. * @throws IOException
  84. */
  85. private void printContent(InputStream is) throws IOException {
  86. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  87. String line;
  88. while ((line=br.readLine()) != null) {
  89. System.out.println(line);
  90. }
  91. if (is != null) {
  92. is.close();
  93. }
  94. if (br != null) {
  95. br.close();
  96. }
  97. }
  98. }

2       通过ResourceLoader获取资源

在Spring里面还定义有一个ResourceLoader接口,该接口中只定义了一个用于获取Resource的getResource(String location)方法。它的实现类有很多,这里我们先挑一个DefaultResourceLoader来讲。DefaultResourceLoader在获取Resource时采用的是这样的策略:首先判断指定的location是否含有“classpath:”前缀,如果有则把location去掉“classpath:”前缀返回对应的ClassPathResource;否则就把它当做一个URL来处理,封装成一个UrlResource进行返回;如果当成URL处理也失败的话就把location对应的资源当成是一个ClassPathResource进行返回。

  1. @Test
  2. public void testResourceLoader() {
  3. ResourceLoader loader = new DefaultResourceLoader();
  4. Resource resource = loader.getResource("http://www.google.com.hk");
  5. System.out.println(resource instanceof UrlResource); //true
  6. //注意这里前缀不能使用“classpath*:”,这样不能真正访问到对应的资源,exists()返回false
  7. resource = loader.getResource("classpath:test.txt");
  8. System.out.println(resource instanceof ClassPathResource); //true
  9. resource = loader.getResource("test.txt");
  10. System.out.println(resource instanceof ClassPathResource); //true
  11. }

ApplicationContext接口也继承了ResourceLoader接口,所以它的所有实现类都实现了ResourceLoader接口,都可以用来获取Resource。

对于ClassPathXmlApplicationContext而言,它在获取Resource时继承的是它的父类DefaultResourceLoader的策略。

FileSystemXmlApplicationContext也继承了DefaultResourceLoader,但是它重写了DefaultResourceLoader的getResourceByPath(String path)方法。所以它在获取资源文件时首先也是判断指定的location是否包含“classpath:”前缀,如果包含,则把location中“classpath:”前缀后的资源从类路径下获取出来,当做一个ClassPathResource;否则,继续尝试把location封装成一个URL,返回对应的UrlResource;如果还是失败,则把location指定位置的资源当做一个FileSystemResource进行返回。

3       在bean中获取Resource的方式

通过上面内容的介绍,我们知道,在bean中获取Resource主要有以下几种方式:

1.直接通过new各种类型的Resource来获取对应的Resource。

2.在bean里面获取到对应的ApplicationContext,再通过ApplicationContext的getResource(String path)方法获取对应的Resource。

3.直接创建DefaultResourceLoader的实例,再调用其getResource(String location)方法获取对应的Resource。

4.通过依赖注入的方式把Resource注入到bean中。示例如下:

类ClassA

  1. public class ClassA {
  2. //持有一个Resource属性
  3. private Resource resource;
  4. public void printContent() {
  5. if (resource != null && resource.exists()) {
  6. if (resource.isReadable()) {
  7. InputStream is;
  8. try {
  9. is = resource.getInputStream();
  10. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  11. String line;
  12. while ((line=br.readLine()) != null) {
  13. System.out.println(line);
  14. }
  15. if (is != null) {
  16. is.close();
  17. }
  18. if (br != null) {
  19. br.close();
  20. }
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }
  26. }
  27. public void setResource(Resource resource) {
  28. this.resource = resource;
  29. }
  30. }

applicationContext.xml文件:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  6. http://www.springframework.org/schema/context
  7. http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  8. <bean id="classA" class="com.xxx.ClassA">
  9. <property name="resource">
  10. <value>classpath:applicationContext.xml</value>
  11. </property>
  12. </bean>
  13. </beans>

从上面可以看到我们有一个类ClassA,其持有一个Resource属性,在Spring bean配置文件中我们直接给ClassA注入了属性resource。其对应的测试代码如下:

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration("classpath:applicationContext.xml")
  3. public class Test1 {
  4. @Autowired
  5. private ClassA classA;
  6. @Test
  7. public void test() {
  8. classA.printContent();
  9. }

通过Spring Resource接口获取资源的更多相关文章

  1. Spring Resource接口获取资源

    1.1.1. Resource简介 在Spring内部实现机制,针对于资源文件(配置的xml文件)有一个统一的接口Resource. 1.1.1.1. 接口定义的方法 1.exists():判断资源文 ...

  2. Bean利用Resource接口获取资源的几种方式

    Resources的类型 获取resource的方式(xml配置正常进行):

  3. [Spring] Resource 资源

    import ch.qos.logback.core.net.SyslogOutputStream; import org.springframework.core.io.ClassPathResou ...

  4. Spring源码分析——资源访问利器Resource之接口和抽象类分析

    从今天开始,一步步走上源码分析的路.刚开始肯定要从简单着手.我们先从Java发展史上最强大的框架——Spring...旗下的资源抽象接口Resource开始吧. 我看了好多分析Spring源码的,每每 ...

  5. 攻城狮在路上(贰) Spring(三)--- Spring 资源访问利器Resource接口

    Spring为了更好的满足各种底层资源的访问需求.设计了一个Resource接口,提供了更强的访问底层资源的能力.Spring框架使用Resource装载各种资源,包括配置文件资源.国际化属性文件资源 ...

  6. Spring源码分析——资源访问利器Resource之实现类分析

    今天来分析Spring的资源接口Resource的各个实现类.关于它的接口和抽象类,参见上一篇博文——Spring源码分析——资源访问利器Resource之接口和抽象类分析 一.文件系统资源 File ...

  7. spring资源访问接口和资源加载接口

    spring 资源访问接口 JDK提供的资源访问类,如java.net.URL.File等,不能很好地满足各种资源的访问需求,比如缺少从类路径或者Web容器的上下文中获取资源的操作类. 鉴于此,spr ...

  8. Resource接口,及资源

    Resource介绍 编码的时候,除了代码本身,我们还需要对外部的资源进行处理.例如:URL资源.URI资源.File资源.ClassPath相关资源.服务器相关资源(VFS等)等等. 而这些资源的处 ...

  9. 基础篇:JAVA资源之IO、字符编码、URL和Spring.Resource

    目录 1 JAVA.IO字节流 2 JAVA.IO字符流 3 乱码问题和字符流 4 字符集和字符编码的概念区分 5 URI概念的简单介绍 6 URL概念及与URL的区别 7 Spring.Resour ...

随机推荐

  1. JavaSE学习笔记(4)---抽象类和接口

    JavaSE学习笔记(4)---抽象类和接口 抽象方法和抽象类 ·抽象方法 使用abstract修饰的方法,没有方法体,只有声明.定义的是一种"规范",就是告诉子类必须要给抽象方法 ...

  2. P4802 [CCO 2015]路短最

    Problem 这题的题意是 求一条 经过 起点和终点的 最长路径.且一个点只能经过一次. 我们设定 \(dis_{i,j}\) 为 i 到 j 的距离(应该没有重边) 要注意的是 不能用 \(Flo ...

  3. gulp常用插件之gulp-useref使用

    更多gulp常用插件使用请访问:gulp常用插件汇总 gulp-useref这是一款可以将HTML引用的多个CSS和JS合并起来,减小依赖的文件个数,从而减少浏览器发起的请求次数.gulp-usere ...

  4. id、css命名规范

    main热点:hot新闻:news下载:download子导航:subnav菜单:menu子菜单:submenu搜索:search友情链接:friendlink页脚:footer版权:copyrigh ...

  5. Disharmony Trees HDU - 3015 树状数组+离散化

    #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using ...

  6. StarUML 2下载、安装、破解全过程

      StarUML官方下载地址:  http://staruml.io/download 破解: ​  1.使用Editplus或者Notepad++等特殊的文本编辑器打开 安装位置下/www/lic ...

  7. 在Spring中使用嵌入式数据库-H2

    Spring3以后开始支持嵌入式数据库,嵌入式数据库目前在市面上有好多种,HSQL,DERBY,H2...今天就主要讲一下h2的使用 对于一个数据库产品来说,主要就是如何存储数据和读取数据了.所谓嵌入 ...

  8. Java_Day4(下)

    Java learning_Day4(下) 本人学习视频用的是马士兵的,也在这里献上 <链接:https://pan.baidu.com/s/1qKNGJNh0GgvlJnitTJGqgA> ...

  9. C++-HDU3400-Line belt[三分]

    将军饮马问题的升级版 二维平面中要从A到D,给出两条线段AB,CD,分别在线段AB,CD,以及空白处的速度为P,Q,R 求最少用时 由于最优位置满足“凸性”,且两条线段可以等价,所以可以采取三分答案迭 ...

  10. [ZJOI2007] 仓库建设 - 斜率优化dp

    大脑真是个很优秀的器官,做事情之前总会想着这太难,真的逼着自己做下去,回头看看,其实也不过如此 很朴素的斜率优化dp了 首先要读懂题目(我的理解能力好BUG啊) 然后设\(dp[i]\)表示处理完前\ ...