zoukankan      html  css  js  c++  java
  • Spring Resource接口获取资源

    本文转自http://elim.iteye.com/blog/2016305 感谢作者

    • Resource
      • 所有的资源都被可以通过 InputStream 这个类来获取,所以也屏蔽了资源的提供者
      • ResourceLoader 接口负责资源的统一加载

    通过Spring Resource接口获取资源

    目录

    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是针对于输入流封装的资源,它的构建需要一个输入流。

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

    2       通过ResourceLoader获取资源

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

    Java代码  
    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

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

    applicationContext.xml文件:

    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.    
    9.    <bean id="classA" class="com.xxx.ClassA">  
    10.       <property name="resource">  
    11.          <value>classpath:applicationContext.xml</value>  
    12.       </property>  
    13.    </bean>  
    14.    
    15. </beans>  

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

    Java代码  
    1. @RunWith(SpringJUnit4ClassRunner.class)  
    2. @ContextConfiguration("classpath:applicationContext.xml")  
    3. public class Test1 {  
    4.    
    5.    @Autowired  
    6.    private ClassA classA;  
    7.     
    8.    @Test  
    9.    public void test() {  
    10.       classA.printContent();  
    11.    }  
    12.     
    13. }  
  • 相关阅读:
    Python接入支付宝进行PC端支付
    python3.6安装pycrypto,pycrytodome和crypto
    Redis
    python时区设置——pytz模块
    redis介绍以及安装
    转译符,re模块,random模块
    正则表达式
    走进模块
    面向对象进阶
    pycharm快捷键
  • 原文地址:https://www.cnblogs.com/panxuejun/p/5898543.html
Copyright © 2011-2022 走看看