zoukankan      html  css  js  c++  java
  • Spring的Resource

    通过Spring Resource接口获取资源(取自http://haohaoxuexi.iteye.com/blog/2016305)
    目录
    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代码 收藏代码

    public class ResourceTest {

    /**
    * ClassPathResource可以用来获取类路径下的资源
    * @throws IOException
    */
    @Test
    public void testClassPath() throws IOException {
    Resource resource = new ClassPathResource("test.txt");
    String fileName = resource.getFilename();
    System.out.println(fileName);
    // resource.getFile(); //获取资源对应的文件
    // resource.getURL(); //获取资源对应的URL
    if (resource.isReadable()) {
    //每次都会打开一个新的流
    InputStream is = resource.getInputStream();
    this.printContent(is);
    }
    }

    /**
    * FileSystemResource可以用来获取文件系统里面的资源,对于FileSystemResource而言我们
    * 可以获取到其对应的输出流。
    * @throws IOException
    */
    @Test
    public void testFileSystem() throws IOException {
    FileSystemResource resource = new FileSystemResource("D:\test.txt");
    if (resource.isReadable()) {
    //FileInputStream
    printContent(resource.getInputStream());
    }
    if (resource.isWritable()) {
    //每次都会获取到一个新的输出流
    OutputStream os = resource.getOutputStream();
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
    bw.write("你好,中国!");
    bw.flush();
    if (os != null) {
    os.close();
    }
    if (bw != null) {
    bw.close();
    }
    }
    }

    /**
    * 针对于URL进行封装的Resource,可用来从URL获取资源内容
    * @throws Exception
    */
    @Test
    public void testURL() throws Exception {
    UrlResource resource = new UrlResource("http://www.google.com.hk");
    if (resource.isReadable()) {
    //URLConnection对应的getInputStream()。
    printContent(resource.getInputStream());
    }
    }

    /**
    * 针对于字节数组封装的Resource,用来从字节数组获取资源内容
    * @throws IOException
    */
    @Test
    public void testByteArray() throws IOException {
    ByteArrayResource resource = new ByteArrayResource("Hello".getBytes());
    //ByteArrayInputStream()
    printContent(resource.getInputStream());
    }

    /**
    * 针对于输入流的Resource,其getInputStream()方法只能被调用一次。
    * @throws Exception
    */
    @Test
    public void testInputStream() throws Exception {
    InputStream is = new FileInputStream("D:\test.txt");
    InputStreamResource resource = new InputStreamResource(is);
    //对于InputStreamResource而言,其getInputStream()方法只能调用一次,继续调用将抛出异常。
    InputStream target = resource.getInputStream(); //返回的就是构件时的那个InputStream
    //is将在printContent方法里面进行关闭
    printContent(target);
    }

    /**
    * 输出输入流的内容
    * @param is
    * @throws IOException
    */
    private void printContent(InputStream is) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    String line;
    while ((line=br.readLine()) != null) {
    System.out.println(line);
    }
    if (is != null) {
    is.close();
    }
    if (br != null) {
    br.close();
    }
    }

    }


    2 通过ResourceLoader获取资源

    在Spring里面还定义有一个ResourceLoader接口,该接口中只定义了一个用于获取Resource的getResource(String location)方法。它的实现类有很多,这里我们先挑一个DefaultResourceLoader来讲。DefaultResourceLoader在获取Resource时采用的是这样的策略:首先判断指定的location是否含有“classpath:”前缀,如果有则把location去掉“classpath:”前缀返回对应的ClassPathResource;否则就把它当做一个URL来处理,封装成一个UrlResource进行返回;如果当成URL处理也失败的话就把location对应的资源当成是一个ClassPathResource进行返回。
    Java代码 收藏代码
    @Test
    public void testResourceLoader() {
    ResourceLoader loader = new DefaultResourceLoader();
    Resource resource = loader.getResource("http://www.google.com.hk");
    System.out.println(resource instanceof UrlResource); //true
    //注意这里前缀不能使用“classpath*:”,这样不能真正访问到对应的资源,exists()返回false
    resource = loader.getResource("classpath:test.txt");
    System.out.println(resource instanceof ClassPathResource); //true
    resource = loader.getResource("test.txt");
    System.out.println(resource instanceof ClassPathResource); //true
    }

    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代码 收藏代码
    public class ClassA {

    //持有一个Resource属性
    private Resource resource;

    public void printContent() {
    if (resource != null && resource.exists()) {
    if (resource.isReadable()) {
    InputStream is;
    try {
    is = resource.getInputStream();
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    String line;
    while ((line=br.readLine()) != null) {
    System.out.println(line);
    }
    if (is != null) {
    is.close();
    }
    if (br != null) {
    br.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }

    public void setResource(Resource resource) {
    this.resource = resource;
    }

    }

    applicationContext.xml文件:
    Xml代码 收藏代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="classA" class="com.xxx.ClassA">
    <property name="resource">
    <value>classpath:applicationContext.xml</value>
    </property>
    </bean>

    </beans>

    从上面可以看到我们有一个类ClassA,其持有一个Resource属性,在Spring bean配置文件中我们直接给ClassA注入了属性resource。其对应的测试代码如下:
    Java代码 收藏代码
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class Test1 {

    @Autowired
    private ClassA classA;

    @Test
    public void test() {
    classA.printContent();
    }

    }

  • 相关阅读:
    C#中虚方法与抽象方法的区别
    关于计算同一个用户购买日期间隔查询语句
    pandas 讲数据分组之后保留前N行方法
    关于Mysql隐式转化及注意事项与cast函数运用
    Mysql 去重
    记一个pandas 分组之后.head()返回的数据问题
    Failed to introspect Class xxxx
    golang 推荐学习记录
    Java内存区域
    Struts2中采用Json返回List对象数据为空解决方案
  • 原文地址:https://www.cnblogs.com/LvLoveYuForever/p/5707423.html
Copyright © 2011-2022 走看看