Sprint资源访问

目录

 

一、资源抽象接口

1、传统java中的资源加载

2、Spring中的Resource接口

二、资源加载

1、资源地址表达式

2、资源加载器

三、总结


一、资源抽象接口

1、传统java中的资源加载

通过ClassLoader类加载器进行的。代码如下:

Thread.currentThread().getContextClassLoader().getResource("com/demo/SimpleJava.class");
SimpleJava.class.getClassLoader().getResource("com/demo/SimpleJava.class");
ClassLoader.getSystemResource("com/demo/SimpleJava.class");
SimpleJava.class.getResource("SimpleJava.class");

每个类加载器加载资源时,都有自己固定的位置,也就是实例化类加载器时传递的url,相当于类加载器加载的资源的仓库,也只会在自己的的仓库中寻找资源,而classPath下的资源,都是AppClassLoader类进行加载。 

对于通过SimpleJava.class.getResource进行的资源加载,我们可以通过分析源码:

//这是class类中进行资源加载的方法
public java.net.URL getResource(String name) {
    name = resolveName(name); //通过解析资源名称,如果是以/开头,会在classpath下找寻,name必须为包含全限定名称的路径。
    //上面的例子中SimpleJava.class.getResource("SimpleJava.class")的路径可以换成:/com/demo/SimpleJava.class,如果不是以/开头,则会在相对于SimpleJava.class的目录下找寻。
    ClassLoader cl = getClassLoader0();
    if (cl==null) {
        return ClassLoader.getSystemResource(name);
    }
    return cl.getResource(name);
}

2、Spring中的Resource接口

传统的Java资源文件的访问通过JDK中的File、URL类难以满足各种不同需求的资源加载,这里有Spring中设计的org.springframework.core.io.Resource接口提供更加强大的访问底层资源的能力。

下面是Resource接口的主要方法:

boolean exists():资源是否存在;
boolean isOpen():资源是否打开;
URL getURL() throws IOException:如果底层资源可以表示成URL,该方法返回对应的URL对象;
File getFile() throws IOException:如果底层资源对应一个文件,该方法返回对应的File对象;
InputStream getInputStream() throws IOException:返回资源对应的输入流;

Resource具体实现类如下:

ByteArrayResource:二进制数组表示的资源;
ClassPathResource:类路径下的资源,资源以相对于类路径的方式表示;
FileSystemResource:文件系统资源,资源以文件系统路径的方式表示;
InputStreamResource:以输入流返回表示的资源;
ServletContextResource:为访问访问Web容器上下文中的资源而设计的类,负责以相对于Web应用程序根目录的路径加载资源,它支持以流和URL的方式访问,在WAR解包的情况下,也可以通过File的方式访问,还可以直接从JAR包中访问资源;
URLResource:Url封装了java.net.URL,它使用户能够访问任何可以通过URL表示的资源,如文件系统的资源、HTTP资源、FTP资源;
PathResource:Spring4.0提供的读取资源文件的新类。Path封装了java.net.URL、java.nio.file.Path、文件系统资源,它使用户能够访问任何可以同哟URL、Path、系统文件路径表示的资源,如文件系统的资源、Http资源、FTP资源;

如下分别通过FileSystemResource和ClassPathResource访问同一个文件资源:

/**
     * Sping获取资源的接口
     * 继承的接口有:WritableResource
     * 实现类有:
     * PathResource
     * ClassPathResource
     * FileSystemResource等
     */
    @Test
    public void test_resource() throws IOException {
        //使用系统文件路径方式加载资源
        //WritableResource接口继承接口Resource,添加了 isWritable/getOutputStream 方法
        String filePath = "/Users/admin/spr-mybatis-web/src/main/resources/note/note.txt";
        WritableResource res1 = new PathResource(filePath);

        //使用类路径方式加载资源
        Resource res2 = new ClassPathResource("note/note.txt");

        //使用WritableResource接口读取资源文件
        OutputStream stream1 = res1.getOutputStream();
        stream1.write("这个是测试".getBytes());
        stream1.close();

        //使用Resource接口读取资源
        InputStream ins1 = res1.getInputStream();
        InputStream ins2 = res2.getInputStream();

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        int i;
        while ((i = ins1.read()) != -1) {
            bos.write(i);
        }
        System.out.println(bos.toString());
        System.out.println(res1.getFilename());
        System.out.println(res2.getFilename());
    }

获取到资源后,可以通过getFileName()获取方法名,通过getFile()获取资源对应的File文件,通过getInputStream()直接获取文件的输入流,还可通过createRelative(String relativePath)在资源相对地址上创建新的文件。

如下是在Web应用中通过ServletContextResource以相对于Web应用根目录的方式访问文件资源:

Resource res3 = new ServletContextResource(application,"/WEB-INF/classes/conf/file1.txt");

可以通过EncodedResource对资源进行编码,保证资源内容操作的正确性,如下:

Resource res = new ClassPathResource("conf/file1.txt");
EncodedResource encRes = new EncodedResource(res,"UTF-8");
String content  = FileCopyUtils.copyToString(encRes.getReader());
System.out.println(content); 

二、资源加载

为了访问不同类型的资源,必须使用相应的Resorce实现类,这是比较麻烦的,spring提供了一个强大的加载资源的机制,能够自动识别不同的资源类型。

1、资源地址表达式

地址前缀 示例 对应的资源类型
classpath: classpath:com/bean/bean.xml 表示从类路径加载资源,classpath:和classpath:/是等价的,都是相对于类的根路径。资源文件可以在标准的文件系统中,也可以在jar或zip的类包中
file: file:/com/bean/bean.xml 使用UrlResource从文件系统目录中装载资源,可采用绝对或相对路径
http:// http://www.csdn.bean.xml 使用UrlResource从Web服务器中装载资源
ftp:// ftp://www.csdn.bean.xml 使用UrlResource从FTP服务器中装载资源
没有前缀 com/bean/bean.xml 根据ApplicationContext的具体实现类采用对应类型的Resource

其中,classpath:和classpath*:的区别在于classpath*:会扫描所有类路径下出现的资源,而classpath只会在第一个加载的包下查找,即就是只加载一个资源文件。

匹配风格资源地址支持3种:

?:匹配文件中的一个字符
* :匹配文件中的任意字符
** :匹配多层路径
如:file:/com/bean/bea?.xml

2、资源加载器

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

2-1、Resource接口

位于包 org.springframework.core.io 下,提供了一些基本方法,如 exists()/getResource()等方法

2-2、ResourcePatternResolver接口

位于包 org.springframework.core.io.support 下,继承了接口ResourceLoader,增加了Resource[] getResources(String var1)方法,可以看出相对与ResourceLoader接口而言增加了批量加载文件方法。添加了资源匹配模式表达式,但不支持匹配风格地址加载资源。

2-3、PathMatchingResourcePatternResolver类

位于包 org.springframework.core.io.support 下,实现了接口 ResourcePatternResolver。新增了支持匹配风格地址加载资源。

具体代码如下:

    ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    Resource[] resources = resourcePatternResolver.getResources("classpath*:note/not?.txt");
    for(Resource resource:resources){
       System.out.println(resource.getFilename());
    }

三、总结

1、传统java中的资源加载,是通过类加载器进行获取资源;

2、Spring获取资源提供了Resource接口,该接口提供了获取资源的及其相关方法,并针对不同资源获取方式提供了不同的实现类;

3、为了访问不同类型的资源,必须使用相应的Resorce实现类,这是比较麻烦的,spring提供了一个强大的加载资源的机制,能够自动识别不同的资源类型。Spring为其提供了资源表达式和资源加载器接口和实现类。

 

 

你可能感兴趣的:(Sprint资源访问)