spring资源操作

spring资源操作(Resource)

Java的标准java.net.URL类和各种URL前缀的处理标准处理程序无法满足所有对low-level资源的访问,比如:没有标准优化的URL实现可用于访问需要从类路径或相对于ServletContext获取的资源。并缺少某些Spring所需要的功能。如检测某资源是否存在等。而Spring的Resource声明了访问low-level资源的能力。

Spring Resource

Resource接口

Resource接口是Spring资源访问策略的抽象,它本身不提供任何资源访问实现,具体的资源访问由该接口的实现类完成(每一个实现类代码表一种资源访问策略)。Resource一般包含这些实现类:UrlResourceClassPathResourceFileSystemResourceServletContextResourceInputStreamResourceByteArrayResource

UrlResource访问网络资源

Resource的一个实现类,用来访问网络资源,它支持URL的绝对路径
http:该前缀用于访问基于HTTP协议的网络资源。
ftp:该前缀用于访问基于FTP协议的网络资源
file:该前缀用于从文件系统中读取资源。

示例
    //UrlResource访问网络资源
    public class UrlResourceDemo {
        public static void loadUrlResource(String path){
            //创建Resource实现类的对象UrlResource
            try {
                UrlResource url = new UrlResource(path);
                //获取资源信息
                System.out.println("url.getURL()" + url.getURL());
                System.out.println("url.getFilename() = " + url.getFilename());
                System.out.println("url.getDescription() = " + url.getDescription());
                System.out.println("url.getInputStream() = " + url.getInputStream());
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        public static void main(String[] args) {
            //http前缀
            UrlResourceDemo.loadUrlResource("http://www.baidu.com");
            /*
            url.getURL()http://www.baidu.com
            url.getFilename() =
            url.getDescription() = URL [http://www.baidu.com]
            url.getInputStream() = sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@7591083d
            * */

            //file前缀,下面的写法需要注意文件要放在根路径下(spring6),也可以写如绝对路径
            loadUrlResource("file:louis.txt");
            /*
            * url.getURL()file:louis.txt
            url.getFilename() = louis.txt
            url.getDescription() = URL [file:louis.txt]
            url.getInputStream() = java.io.BufferedInputStream@7eda2dbb
            * */
        }
    }
ClassPathResource访问路径下资源

ClassPathResource用来访问类加载路径下的资源,相对于其他的Resource实现类,其主要优势是方便访问类加载路径里的资源,尤其对于web应用,ClassPathResource可自动搜索位于classes下的资源文件,无需使用绝对路径

示例
package com.louis.resource;

import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author XRY
 * @date 2023年06月28日18:40
 */
//访问类路劲下的资源
public class ClassPathResourceDemo {
    public static void loadClassPathResource(String url){
        //创建对象
        ClassPathResource classPathResource = new ClassPathResource(url);
        System.out.println("classPathResource.getFilename() = " + classPathResource.getFilename());
        System.out.println("classPathResource.getDescription() = " + classPathResource.getDescription());
        //获取文件内容
        try {
            InputStream inputStream = classPathResource.getInputStream();
            byte[] b = new byte[1024];
            int len = 0;
            while((len = inputStream.read(b)) != -1){
                System.out.println(new String(b, 0, len));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        //是相对路径,可以放在resources下
        loadClassPathResource("louis.txt");
        /*
        * classPathResource.getFilename() = louis.txt
          classPathResource.getDescription() = class path resource [louis.txt]
          Hi,louis
        * */
    }
}
FileSystemResource访问文件系统资源

Spring提供的FileSystemResource类用于访问文件系统资源,使用FileSystemResource来访问文件系统资源并没有太大的优势,因为java提供的File类也可以用于访问文件系统资源。

示例
public class FileSystemResourceDemo {
    public static void  loadFileResource(String path){
        //创建对象
        FileSystemResource fileResource = new FileSystemResource(path);
        System.out.println("fileResource.getFilename() = " + fileResource.getFilename());
        System.out.println("fileResource.getDescription() = " + fileResource.getDescription());
        //创建输入流对象
        try {
            InputStream inputStream = fileResource.getInputStream();
            byte[] bytes = new byte[1024];
            int len = 0;
            while((len=inputStream.read(bytes))!=-1){
                System.out.println(new String(bytes, 0, len));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        //相对路径或绝对路径
        loadFileResource("C:\\Users\\XRY\\Desktop\\text.txt");
        /*
        *   fileResource.getFilename() = text.txt
            fileResource.getDescription() = file [C:\Users\XRY\Desktop\text.txt]
            测试fileSystemResource
        * */
    }
}

在这里插入图片描述

ServletContextResource

这是ServletContext资源的Resource实现,它解释相关Web应用程序根目录中的相对路径,它始终支持流(stream)访问和URL访问,但只有在扩展web应用程序存档且资源实际位于文件系统上时才允许java的io,File访问,无论他是在文件系统上扩展还是直接从JAR或其他地方访问,实际上都是依赖Servlet容器。

InputStreamResource

InputStreamResource是给定的输入流InputStream的Resource实现,它的使用场景在没有特定的资源实现的时候使用(感觉和@Component的使用场景很相似)。与其他Resource实现相比,这是已经打开资源的描述符,因此,它的isOpen()方法返回true,如果需要将资源描述符保留在某处或者需要多次读取流,建议不要使用。

ByteArrayResource

字节数组的Resource实现类。通过给定的数组创建一个ByteArrayInputStream。它对于从任何给定的字节数组加载内容非常有用,而无需求助于单次使用的InoutStreamResource.


ResourceLoader接口

Spring ResourceLoader概述

ResourceLoader:该接口实现类的实例可以获得一个Resource实例
ResourceLoaderAware:该接口实现类的实例将获得一个ResourceLoader的引用

ResourceLoader

在ResourceLoader接口主要定义了一个方法:
getResource(String location):该接口,用于返回一个Resource实例。

ApplicationContext实现类都实现ResourceLoader接口,因此ApplicationContext可直接获取Resource实例。

示例
@Test
public void testClassPathXmlApplicationContext() {
    ApplicationContext context = new ClassPathXmlApplicationContext();
    Resource resources = context.getResource("louis.txt");
    System.out.println(resources.getFilename());
    /*
    * louis.txt
    * */
}


@Test
public void testFileSystemApplicationContext(){
    ApplicationContext context = new FileSystemXmlApplicationContext();
    Resource resource = context.getResource("louis.text");
    System.out.println(resource.getFilename());
    /*
    * louis.text
    * */
}

Spring采用ApplicationContext相同的策略来访问资源,如果ApplicationContext是FileSystemApplicationContext,返回的就是FileSystemResource实例,如果ApplicationContext是ClassPathXmlApplicationContext,返回的就是ClassPathResource

总结:

当spring应用需要进行资源访问时,实际上并不需要直接使用Resource实现类,而是调用ResourceLoader实例的getResource()方法获取资源,ResourceLoader将会负责选择Resource实现类,也就是确定具体的资源访问策略,从而将应用程序和具体的资源访问策略分开来,另外,使用ApplicationContext访问资源时,可通过不同前缀指定强制使用指定的ClassPathResource、FileSystemResource等实现类。

ResourceLoaderAware

ResourceLoaderAware接口实现类的实例将获得一个ResourceLoader的引用,ResourceLoaderAware接口也提供了一个setResourceLoader()方法,该方法由spring容器负责调用,spring容器会将一个ResourceLoader对象作为该方法的参数传入。
如果把实现ResourceLoaderAware接口的Bean类部署在Spring容器中,Spring容器会将自身当成ResourceLoader作为setResourceLoader()方法的参数传入。由于ApplicationContext的实现类都实现了ResourceLoader接口,Spring容器自身完全可作为ResourceLoader使用。

测试通过get、set方法创建的ResourceLoader和Spring传入的ResourceLoader是否为同一对象

自主创建
public class TestResourceLoaderAware implements ResourceLoaderAware {
    private ResourceLoader resourceLoader;


    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    public ResourceLoader getResourceLoader() {
        return this.resourceLoader;
    }
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="testResourceLoaderAware" class="com.louis.resourceloaderaware.TestResourceLoaderAware"></bean>
</beans>
测试
@Test
public void testAware(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
    TestResourceLoaderAware loaderAware = applicationContext.getBean("testResourceLoaderAware", TestResourceLoaderAware.class);
    ResourceLoader resourceLoader = loaderAware.getResourceLoader();
    System.out.println(resourceLoader == applicationContext);
    /*true*/
}

Resource作为属性

Bean实例需要访问资源,有如下的两种方式:

1、代码中获取Resource实例
2、使用依赖注入

对于第一种方式,当程序获取Resource实例时,总需要提供Resource所在的位置,这意味着资源所有的物理位置将被耦合到代码中,如果资源位置发生改变,则必须改写程序,因此,通常建议使用方式二,让Sprig为Bean实例依赖注入资源。

Spring为Bean实例依赖注入资源
步骤
1、创建ResourceBean类
public class ResourceBean {
    private Resource resource;

    public Resource getResource() {
        return resource;
    }

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

    public void parse(){
        System.out.println(resource.getFilename());
        System.out.println(resource.getDescription());
    }
}
2、使用配置文件(bean-di.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
       <bean id="resourceBean" class="com.louis.di.ResourceBean">
           <property name="resource" value="louis.txt"></property>
       </bean>
</beans>
3、测试
public class TestResourceBean {
    @Test
    public void testResourceBean(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean-di.xml");
        ResourceBean resource = context.getBean("resourceBean", ResourceBean.class);
        resource.parse();
       /*
        * louis.txt
          class path resource [louis.txt]
        * */
    }
}

应用程序上下文和资源路径

概述

不管以怎样的方式创建ApplicationContext实例,都需要为Application指定配置文件,Spring允许使用一份或多分XML配置文件,当程序创建ApplicationContext实例时,通常也是以Resource的方式访问配置文件,所以ApplicationContext完全支持ClassPathResource、FileSystemResource、ServletContextResource等资源的访问方式。

ApplicationContext确定资源访问策略通常有两种方式

  • 使用ApplicationContext实现类指定访问路径
  • 使用前缀指定访问路径

ApplicationContext实现类执行访问路径

创建ApplicationContext对象时,通常可以实现如下实现类:

  • ClassPathXMLApplicationContext:对应使用ClassPathResource进行资源访问
  • FileSystemXmlApplicationCOntext:对应使用FileSystemResource进行资源访问
  • XmlWebApplicationContext:对应使用ServletContextResource进行资源访问

当使用ApplicationContext不同实现类时,就意味着Spring使用响应的资源访问策略,之前写的就是这种方式。

使用前缀指定访问路径

测试类
public class TestDemo {
    public static void main(String[] args){
        //classpath:就表示通过前缀查找类路径下的资源
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean-prefix.xml");
        Resource resource = context.getResource("louis.txt");
        System.out.println("resource =  " + resource.getDescription());
        /*resource =  class path resource [louis.txt]*/
    }
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="prefixResource" class="com.louis.prefix.TestDemo"></bean>
</beans>
classpath通配符使用

classpath*:前缀提供了加载多个XMl配置文件的能力,当使用classpath*:前缀来指定XML配置文件时,系统将搜索类加载路径,找到与文件名匹配的文件,分别加载文件中的配置定义,最后合并成一个ApplicationContext

ApplicationContext context = new ClassPathXmlApplicationContext("classpath\*:bean.xml");

如果不采用classpath*:前缀,而是改为classpath:前缀,Spring则只加载第一个符合条件的XML文件

注意:

classpath*:前缀仅对ApplicationContext有效,实际情况是,创建ApplicationContext时,分别访问多个配置文件(通过ClassLoader的getResource方法实现)。因此,classpath*:前缀不可用于Resource。

通配符其他使用

一次加载多个配置文件的方式:指定配置文件时使用通配符

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean*.xml");

Spring允许将classpath*:前缀和通配符结合使用

ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:bean*.xml");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值