Spring笔记――12.访问资源

Spring把文件,二进制流统称为资源。Spring改价了访问资源的策略,它提供了一个Resource接口,该接口提供了更强的资源访问能力,Spring架构本身大量使用了Resource来访问底层数据。

Spring将所有形式的资源表现概括成一个Resource接口。如下所示(下面的接口定义是被简化的,有意省略了一些东西,以便突出重点)

public interface Resource {
    InputStream getInputStream();
    URL getURL();
    File getFile();
    boolean exists();
}

getInputStream方法能够定位并打开资源,返回资源对应的输入流。每次调用都返回新的输入流。调用者必须负责关闭输入流。

exists返回所指向文件是否存在。

isOpen返回资源是否打开。有些资源读取结束必须关闭,以防止资源泄露。

getDescription返回资源的描述信息。

getFile返回资源对应的File对象。

getURL返回资源对应的URL对象。最后两个是传统的方式,仅仅在简单方式访问受阻时才用。

此接口并没有任何资源访问实现逻辑。而对于不同资源,架构也提供了不同的resource实现类。并且Resource可以独立于Spring架构使用。虽然这里面也有接口与实现类的耦合,但这是指工具类的耦合,代码污染很小。


Resource实现类

resource接口是Spring资源访问的接口,Spring提供了很多接口实现类

  • UrlResource:访问网络资源的实现类

  • ClassPathResource:访问类加载路径里资源的实现类

  • FileSystemResource:访问文件系统里资源的实现类

  • ServletContextResource:访问相对于ServletContext路径下的资源的实现类

  • InputStreamResource:访问输入流资源的实现类

  • ByteArrayResource:访问字节数组资源的实现类


访问网络资源

package com.cm;
import java.util.Iterator;
import java.util.List;
import org.dom4j.*;
import org.dom4j.io.SAXReader;
import org.springframework.core.io.UrlResource;
public class test {
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		UrlResource ur = new UrlResource("file:book.xml");
		System.out.println(ur.getFilename());
		System.out.println(ur.getDescription());
		SAXReader reader = new SAXReader();
		Document doc = reader.read(ur.getFile());
		Element el = doc.getRootElement();
		List l = el.elements();
		for (Iterator it = l.iterator(); it.hasNext();) {
			Element book = (Element) it.next();
			List ll = book.elements();
			for (Iterator it2 = ll.iterator(); it2.hasNext();) {
				Element eee = (Element) it2.next();
				System.out.println(eee.getText());
			}
		}
	}
}

代码中的file:标识访问文件系统,也就是本地磁盘文件。此例子中的book.xml文件应该在当前路径下。此外还可以用http:、ftp:用于标识在这两种协议下访问资源。


访问类加载路径下资源

ClassPathResource cr=new ClassPathResource("book.xml");

此处是手动创建。更多的时候架构能够在执行某个方法时,接受一个代表资源路径的字符串参数,参数有classpath前缀时,会自动创建ClassPathResource对象。我们注意到访问网络资源与类加载路径下资源仅仅有一行代码的不同,这也是Spring的优势。

访问文件系统资源

FileSystemResource fr=new FileSystemResource("book.xml");

资源字符串确定的资源在本地,无需任何前缀修饰。


访问应用相关资源

Spring提供了ServletContextResource类来访问Web Context下相对路径下的资源,这个类的构造器会接收一个代表资源位置的字符串(相对于Web应用根目录)。下面的例子中,我们把一个文件放在WEB-INF路径下。由于JSP不能直接访问WEB-INF路径下的任何资源,因此我们需要JSP使用ServletContextResource类来访问。

<%
    ServletCOntextResource src=new Servlet ContextResource(application,"WEB-INF/book.xml");
    --剩下的一样
%>


访问字节数组资源

Spring提供了InputStreanResource来访问二进制输入流文件,不过不推荐使用。


ResourceLoader接口和ResourceLoaderAware接口

Spring提供如下两个标志性接口:

  • ResourceLoader的实现类可以获得一个Resource实例

  • ResourceLoaderAware的实现实例可以获得一个ResourceLoader的引用。

在ResourceLoader接口中有个getResource(String location)方法,可以范湖一个Resource实例。ApplicationContext实现类都已经实现了ResourceLoader接口,所以它们可以直接获得Resource实例。请看!

ApplicationContext ctx=new ClassPathXmlAPplicaitonContext("beans.xml");
Resource res=ctx.getResource("some/resource/path/myfile.txt");

applicationContext也可以使用FileSystemXmlApplicationContext,XmlWebApplicationContext或者ServletContextResource这几个实现类,相应的,resource的实现策略也随之改变,我们要做的只是使用getResource方法即可。不过我们可以在getRersource的url参数中使用classpath、file、http等前缀来强制指定。当然不加前缀就根据ApplicationContext实现类类型决定了。

ResourceLoaderAware提供了一个setResourceLoader方法,此方法由容器调用,容器会为该方法传入一个ResourceLoader对象。只要把实现了ResourceLaoderAware接口的bean布置在xml中,容器会把自己当做loader传入set方法,因为ApplicationContext的实现类都实现了ResourceLoader接口。

public class TestBean implements ResourceLoaderAware {
	private ResourceLoader rd;
	public ResourceLoader getResourceLoader() {
		return rd;
	}
	@Override
	public void setResourceLoader(ResourceLoader arg0) {
		// TODO Auto-generated method stub
		this.rd = arg0;
	}
}
public class test {
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
		TestBean tb = ctx.getBean("test", TestBean.class);
		ResourceLoader rl = tb.getResourceLoader();
		System.out.println(rl == ctx);
	}
}

上述代码会输出true,意味着通过接口实现bean的get方法得到的ResourceLoader与容器本身是同一个。


使用Resource作为属性

前面的访问资源策略,要么需要通过Resource实现类,要么需要通过ApplicationContext获取。不过当bean实例需要访问资源的时候,架构提供了一种更好的方法:直接通过依赖注入,在bean中设定一个private Resource res实例变量。这样,我们就无需在bean代码中获取Resource实例,资源的url路径也就无需耦合到代码中了。

public class resource {
	private Resource res;
	public void parse() throws Exception {
		System.out.println(res.getFilename());
		System.out.println(res.getDescription());
	}
	public Resource getRes() {
		return res;
	}
	public void setRes(Resource res) {
		this.res = res;
	}
}
<bean id="resource" class="com.cm.resource"
    p:res="classpath:book.xml"/>

配置文件中指明了资源文件的位置,使用类加载路径去加载文件。


ApplicationContext中使用资源

无论以怎样的策略创建ApplicationC实例,都要配置xml文件。之前我们一直使用的是ClassPathXmlApplicationContext策略,除此之外还有FileSystemXmlApplicationContext和XmlWebApplicationContext策略。文件url没有任何前缀的话就按照这些实现类的策略了。如果url有前缀,就强制按照前缀策略。此外,我们可以使用*符号来加载一系列文件。

本文出自 “指尖轻飞” 博客,谢绝转载!

你可能感兴趣的:(spring,resource)