`
jinnianshilongnian
  • 浏览: 21424228 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2403122
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:2996146
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5630387
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:257181
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1592644
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:248792
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5845630
Group-logo
跟我学Nginx+Lua开...
浏览量:697465
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:779839
社区版块
存档分类
最新评论

【第四章】 资源 之 4.2 内置Resource实现 ——跟我学spring3

阅读更多

 

4.2  内置Resource实现

4.2.1  ByteArrayResource

       ByteArrayResource代表byte[]数组资源,对于“getInputStream”操作将返回一个ByteArrayInputStream。

首先让我们看下使用ByteArrayResource如何处理byte数组资源:

 

java代码:
	
package cn.javass.spring.chapter4;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Test;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
public class ResourceTest {
@Test
public void testByteArrayResource() {
Resource resource = new ByteArrayResource("Hello World!".getBytes());
        if(resource.exists()) {
            dumpStream(resource);
        }
}
}

 

是不是很简单,让我们看下“dumpStream”实现:

 

java代码:
private void dumpStream(Resource resource) {
        InputStream is = null;
        try {
            //1.获取文件资源
            is = resource.getInputStream();
            //2.读取资源
            byte[] descBytes = new byte[is.available()];
            is.read(descBytes);
            System.out.println(new String(descBytes));
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                //3.关闭资源
                is.close();
            } catch (IOException e) {
            }
        }
    }

 

    让我们来仔细看一下代码,dumpStream方法很抽象定义了访问流的三部曲:打开资源、读取资源、关闭资源,所以dunpStrean可以再进行抽象从而能在自己项目中使用;byteArrayResourceTest测试方法,也定义了基本步骤:定义资源、验证资源存在、访问资源。

 

       ByteArrayResource可多次读取数组资源,即isOpen ()永远返回false。

 

1.2.2  InputStreamResource

       InputStreamResource代表java.io.InputStream字节流,对于“getInputStream ”操作将直接返回该字节流,因此只能读取一次该字节流,即“isOpen”永远返回true。

       让我们看下测试代码吧:

 

java代码:
@Test
public void testInputStreamResource() {
   ByteArrayInputStream bis = new ByteArrayInputStream("Hello World!".getBytes());
   Resource resource = new InputStreamResource(bis);
    if(resource.exists()) {
       dumpStream(resource);
    }
    Assert.assertEquals(true, resource.isOpen());
}
   

 

       测试代码几乎和ByteArrayResource测试完全一样,注意“isOpen”此处用于返回true。

 

4.2.3  FileSystemResource

       FileSystemResource代表java.io.File资源,对于“getInputStream ”操作将返回底层文件的字节流,“isOpen”将永远返回false,从而表示可多次读取底层文件的字节流。

       让我们看下测试代码吧:

 

java代码:
@Test
public void testFileResource() {
File file = new File("d:/test.txt");
    Resource resource = new FileSystemResource(file);
    if(resource.exists()) {
        dumpStream(resource);
    }
    Assert.assertEquals(false, resource.isOpen());
}
 

 

       注意由于“isOpen”将永远返回false,所以可以多次调用dumpStream(resource)。

 

4.2.4  ClassPathResource

       ClassPathResource代表classpath路径的资源,将使用ClassLoader进行加载资源。classpath 资源存在于类路径中的文件系统中或jar包里,且“isOpen”永远返回false,表示可多次读取资源。

       ClassPathResource加载资源替代了Class类和ClassLoader类的“getResource(String name)”和“getResourceAsStream(String name)”两个加载类路径资源方法,提供一致的访问方式。

ClassPathResource提供了三个构造器:

         public ClassPathResource(String path):使用默认的ClassLoader加载“path”类路径资源;

         public ClassPathResource(String path, ClassLoader classLoader)使用指定的ClassLoader加载“path”类路径资源;

比如当前类路径是“cn.javass.spring.chapter4.ResourceTest”,而需要加载的资源路径是“cn/javass/spring/chapter4/test1.properties”,则将加载的资源在“cn/javass/spring/chapter4/test1.properties”;

         public ClassPathResource(String path, Class<?> clazz)使用指定的类加载“path”类路径资源,将加载相对于当前类的路径的资源;

比如当前类路径是“cn.javass.spring.chapter4.ResourceTest”,而需要加载的资源路径是“cn/javass/spring/chapter4/test1.properties”,则将加载的资源在“cn/javass/spring/chapter4/cn/javass/spring/chapter4/test1.properties”;

       而如果需要 加载的资源路径为“test1.properties”,将加载的资源为“cn/javass/spring/chapter4/test1.properties”。

 

       让我们直接看测试代码吧:

1)使用默认的加载器加载资源,将加载当前ClassLoader类路径上相对于根路径的资源:

 

java代码:
@Test
public void testClasspathResourceByDefaultClassLoader() throws IOException {
   Resource resource = new ClassPathResource("cn/javass/spring/chapter4/test1.properties");
    if(resource.exists()) {
        dumpStream(resource);
    }
    System.out.println("path:" + resource.getFile().getAbsolutePath());
    Assert.assertEquals(false, resource.isOpen());
}
 

 

2)使用指定的ClassLoader进行加载资源,将加载指定的ClassLoader类路径上相对于根路径的资源:

 

java代码:
@Test
public void testClasspathResourceByClassLoader() throws IOException {
    ClassLoader cl = this.getClass().getClassLoader();
    Resource resource = new ClassPathResource("cn/javass/spring/chapter4/test1.properties" , cl);
    if(resource.exists()) {
        dumpStream(resource);
    }
    System.out.println("path:" + resource.getFile().getAbsolutePath());
    Assert.assertEquals(false, resource.isOpen());
}

 

3)使用指定的类进行加载资源,将尝试加载相对于当前类的路径的资源:

 

java代码:
@Test
public void testClasspathResourceByClass() throws IOException {
   Class clazz = this.getClass();
    Resource resource1 = new ClassPathResource("cn/javass/spring/chapter4/test1.properties" , clazz);
    if(resource1.exists()) {
        dumpStream(resource1);
    }
    System.out.println("path:" + resource1.getFile().getAbsolutePath());
    Assert.assertEquals(false, resource1.isOpen());
       
    Resource resource2 = new ClassPathResource("test1.properties" , this.getClass());
    if(resource2.exists()) {
        dumpStream(resource2);
   }
    System.out.println("path:" + resource2.getFile().getAbsolutePath());
    Assert.assertEquals(false, resource2.isOpen());
}

       “resource1”将加载cn/javass/spring/chapter4/cn/javass/spring/chapter4/test1.properties资源;“resource2”将加载“cn/javass/spring/chapter4/test1.properties”;

 

4)加载jar包里的资源,首先在当前类路径下找不到,最后才到Jar包里找,而且在第一个Jar包里找到的将被返回:

 

java代码:
@Test
public void classpathResourceTestFromJar() throws IOException {
Resource resource = new ClassPathResource("overview.html");
    if(resource.exists()) {
        dumpStream(resource);
    }
    System.out.println("path:" + resource.getURL().getPath());
    Assert.assertEquals(false, resource.isOpen());
}

 

如果当前类路径包含“overview.html”,在项目的“resources”目录下,将加载该资源,否则将加载Jar包里的“overview.html”,而且不能使用“resource.getFile()”,应该使用“resource.getURL()”,因为资源不存在于文件系统而是存在于jar包里,URL类似于“file:/C:/.../***.jar!/overview.html”。

类路径一般都是相对路径,即相对于类路径或相对于当前类的路径,因此如果使用“/test1.properties”带前缀“/”的路径,将自动删除“/”得到“test1.properties”。

 

4.2.5  UrlResource

       UrlResource代表URL资源,用于简化URL资源访问。“isOpen”永远返回false,表示可多次读取资源。

       UrlResource一般支持如下资源访问:

         http通过标准的http协议访问web资源,如new UrlResource(“http://地址”);

         ftp通过ftp协议访问资源,如new UrlResource(“ftp://地址”);

         file通过file协议访问本地文件系统资源,如new UrlResource(“file:d:/test.txt”);

具体使用方法在此就不演示了,可以参考cn.javass.spring.chapter4.ResourceTest中urlResourceTest测试方法。

 

4.2.6  ServletContextResource

       ServletContextResource代表web应用资源,用于简化servlet容器的ServletContext接口的getResource操作和getResourceAsStream操作;在此就不具体演示了。

 

4.2.7  VfsResource

VfsResource代表Jboss 虚拟文件系统资源。

 

Jboss VFS(Virtual File System)框架是一个文件系统资源访问的抽象层,它能一致的访问物理文件系统、jar资源、zip资源、war资源等,VFS能把这些资源一致的映射到一个目录上,访问它们就像访问物理文件资源一样,而其实这些资源不存在于物理文件系统。

在示例之前需要准备一些jar包,在此我们使用的是Jboss VFS3版本,可以下载最新的Jboss AS 6x,拷贝lib目录下的“jboss-logging.jar”和“jboss-vfs.jar”两个jar包拷贝到我们项目的lib目录中并添加到“Java Build Path”中的“Libaries”中。

让我们看下示例(cn.javass.spring.chapter4.ResourceTest):

 

java代码:
@Test
public void testVfsResourceForRealFileSystem() throws IOException {
//1.创建一个虚拟的文件目录
VirtualFile home = VFS.getChild("/home");
//2.将虚拟目录映射到物理的目录
VFS.mount(home, new RealFileSystem(new File("d:")));
//3.通过虚拟目录获取文件资源
VirtualFile testFile = home.getChild("test.txt");
//4.通过一致的接口访问
Resource resource = new VfsResource(testFile);
if(resource.exists()) {
        dumpStream(resource);
}
System.out.println("path:" + resource.getFile().getAbsolutePath());
Assert.assertEquals(false, resource.isOpen());       
}
@Test
public void testVfsResourceForJar() throws IOException {
//1.首先获取jar包路径
    File realFile = new File("lib/org.springframework.beans-3.0.5.RELEASE.jar");
    //2.创建一个虚拟的文件目录
    VirtualFile home = VFS.getChild("/home2");
    //3.将虚拟目录映射到物理的目录
VFS.mountZipExpanded(realFile, home,
TempFileProvider.create("tmp", Executors.newScheduledThreadPool(1)));
//4.通过虚拟目录获取文件资源
    VirtualFile testFile = home.getChild("META-INF/spring.handlers");
    Resource resource = new VfsResource(testFile);
    if(resource.exists()) {
            dumpStream(resource);
    }
    System.out.println("path:" + resource.getFile().getAbsolutePath());
    Assert.assertEquals(false, resource.isOpen());
}
 

 

       通过VFS,对于jar里的资源和物理文件系统访问都具有一致性,此处只是简单示例,如果需要请到Jboss官网深入学习。

 

原创内容 转自请注明出处【http://sishuok.com/forum/blogPost/list/0/2456.html

 

分享到:
评论
18 楼 1990yalong 2015-08-25  
你好,我在运行最后一个例子时报错,内容如下:
java.lang.NoSuchFieldError: TRACE
at org.jboss.logging.Log4jLogger.translate(Log4jLogger.java:58)
at org.jboss.logging.Log4jLogger.doLogf(Log4jLogger.java:48)
at org.jboss.logging.Logger.tracef(Logger.java:276)
at org.jboss.vfs.spi.RealFileSystem.<init>(RealFileSystem.java:62)
at org.mbox.test.TestVfsResource.testByteArrayInputStream(TestVfsResource.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)


对应错误代码行为:
VirtualFile testFile = home.getChild("report_data2.txt");

我除了按照您所说的加入jboss的两个jar包以外,其他spring和log4j的jar包没动,请问这里我是缺少其他jar包吗?百度没搜索到合适的结果。
17 楼 jinnianshilongnian 2013-11-03  
听见牛在哭 写道
应该引什么包啊

是导错了 不是没导入  你检查下有没有
16 楼 听见牛在哭 2013-11-03  
应该引什么包啊
15 楼 听见牛在哭 2013-11-03  
我用的是MyEclipse自动生成的spring项目,没有手动引入包
14 楼 jinnianshilongnian 2013-11-03  
听见牛在哭 写道
   Resource resource = (Resource) new ClassPathResource("cn/javass/spring/chapter4/ResourceTest.properties");这句代码为什么出现“Multiple markers at this line
- Type mismatch: cannot convert from ClassPathResource to
Resource”的错误提示

是不是导错包了
13 楼 听见牛在哭 2013-11-02  
   Resource resource = (Resource) new ClassPathResource("cn/javass/spring/chapter4/ResourceTest.properties");这句代码为什么出现“Multiple markers at this line
- Type mismatch: cannot convert from ClassPathResource to
Resource”的错误提示
12 楼 jinnianshilongnian 2012-12-04  
qq413041153 写道
问一下楼主,isOpen方法是返回true还是false是spring自己实现的 还是由具体的流决定的?谢谢

具体实现决定
11 楼 qq413041153 2012-12-04  
问一下楼主,isOpen方法是返回true还是false是spring自己实现的 还是由具体的流决定的?谢谢
10 楼 jinnianshilongnian 2012-10-24  
gtandsn 写道
very good ,good job

谢谢
9 楼 gtandsn 2012-10-24  
very good ,good job
8 楼 縌流而上的魚 2012-10-12  

请问 clazz 是在包exercise4/exercise4中吗?

new ClassPathResource("exercise4/test1.properties",clazz); //会到clazz类所在包下找 exercise4/          如果加载clazz所在包的资源 不需要再加包


谢谢拉~已经明白了,我的test1.properties和clazz是在同一级包下,开始没理解现在明白了,非常感谢。还有一个问题,如下:
ClassLoader cl1 = this.getClass().getClassLoader();
		Resource resource = new ClassPathResource("exercise4/test1.properties",cl1);

这里是在ClassLoader的目录下的“exercise4”包下找“test1.properties”文件是吧?ClassLoader就是我工程的类的加载目录?
7 楼 jinnianshilongnian 2012-10-12  
縌流而上的魚 写道
3)使用指定的类进行加载资源,将尝试加载相对于当前类的路径的资源:
这里代码
Class clazz = this.getClass();
		Resource resource1 = new ClassPathResource("exercise4/test1.properties",clazz);
		if (resource1.exists()) {
			dumpStream(resource1);
		}

		System.out.println("path:" + resource1.getFile().getAbsolutePath());

		Assert.assertEquals(false, resource1.isOpen());


Resource resource1 = new ClassPathResource("exercise4/test1.properties",clazz);

这样定义会出错吧?我怎么运行的时候出错了,提示说“exercise4/exercise4/test1.properties”下文件不存在。。为什么加了两个“exercise4/”但是改成“test1.properties”就没有问题了,原因在哪里啊。

请问 clazz 是在包exercise4/exercise4中吗?

new ClassPathResource("exercise4/test1.properties",clazz); //会到clazz类所在包下找 exercise4/          如果加载clazz所在包的资源 不需要再加包
6 楼 縌流而上的魚 2012-10-12  
3)使用指定的类进行加载资源,将尝试加载相对于当前类的路径的资源:
这里代码
Class clazz = this.getClass();
		Resource resource1 = new ClassPathResource("exercise4/test1.properties",clazz);
		if (resource1.exists()) {
			dumpStream(resource1);
		}

		System.out.println("path:" + resource1.getFile().getAbsolutePath());

		Assert.assertEquals(false, resource1.isOpen());


Resource resource1 = new ClassPathResource("exercise4/test1.properties",clazz);

这样定义会出错吧?我怎么运行的时候出错了,提示说“exercise4/exercise4/test1.properties”下文件不存在。。为什么加了两个“exercise4/”但是改成“test1.properties”就没有问题了,原因在哪里啊。
5 楼 zuisanlang 2012-06-21  
请问一下楼主及各位大虾,为什么这一节的testUrlResource()方法中的如下语句:
System.out.println("path:" + resource2.getURL().getPath());
该语句执行后为什么资源的路径没有显示出来呢?
4 楼 jinnianshilongnian 2012-05-18  
b_l_east 写道
jinnianshilongnian 写道
b_l_east 写道
大哥,你空格全是tab么,怎么做到的?!

忘了 估计我没改eclipse的格式



我觉得不错啊,每次用eclipse格式化都是空格,你的tab是怎么修改的,我觉得用tab要好看!

还是用空格吧 tab在不同的编辑器 显示长度不一样
3 楼 b_l_east 2012-05-18  
jinnianshilongnian 写道
b_l_east 写道
大哥,你空格全是tab么,怎么做到的?!

忘了 估计我没改eclipse的格式



我觉得不错啊,每次用eclipse格式化都是空格,你的tab是怎么修改的,我觉得用tab要好看!
2 楼 jinnianshilongnian 2012-05-18  
b_l_east 写道
大哥,你空格全是tab么,怎么做到的?!

忘了 估计我没改eclipse的格式

1 楼 b_l_east 2012-05-18  
大哥,你空格全是tab么,怎么做到的?!

相关推荐

Global site tag (gtag.js) - Google Analytics