Spring中对资源的读取支持
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中对资源的读取支持相关的知识,希望对你有一定的参考价值。
Resource简单介绍
注:所有操作基于配置好的Spring开发环境中。
在Spring中,最为核心的部分就是applicationContext.xml文件,而此配置文件中字符串的功能发挥到了极致。
在Java里面提供了最为原始的IO处理操作支持,但是传统的java.io包中只提供了inputStream与outputStream,虽然是最为常用的输入输出的处理类,但是用其进行一些复杂的资源读取非常麻烦。所以使用PrintStream,Scanner来改善这样的操作处理。但是即便这样,对网络资源,classpath以及一些内部文件的读取也不是很方便。
为此,Spring中设计了一组资源读取的处理接口Resource(org.springframework.core.io.InputStreamSource子接口)。Rresouce中有如下常用处理方法:
public loobean exists(),判断资源是否存在;
public long lastModified(),取得最后一次修改的日期;
public InputStream getInputStream,取得输入流对象。
可以发现Resource对资源的读取很方便,但是要使用Resource还需要依靠不同的子类实现:内存读取(ByteArrayResouce),classpath读取(ClassPathResource),文件读取(FileSystemResource),url读取(UrlResource),web上下文读取(ServletContextResource)。
读取不同的资源
下面对不同的资源类型进行读取:
1,内存操作流的读取:
package cn..io; import java.io.IOException; import java.util.Scanner; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; public class Resource1 { public static void main(String[] args) throws IOException { String info="hello word!!"; Resource resource=new ByteArrayResource(info.getBytes()); if(resource.exists()){ Scanner scan=new Scanner(resource.getInputStream()); scan.useDelimiter(" "); while(scan.hasNext()){ System.out.println(scan.nextLine()); } scan.close(); } } } |
2,文件的 读取:
package cn..io; import java.io.File; import java.io.IOException; import java.util.Scanner; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; public class Resource2 { public static void main(String[] args) throws IOException { String filePath= "C:" + File.separator + "Users" + File.separator + "Administrator" + File.separator + "Desktop"+File.separator+"pom.xml"; File file=new File(filePath); Resource resource=new FileSystemResource(file); if(resource.exists()){ Scanner scan=new Scanner(resource.getInputStream()); scan.useDelimiter(" "); while(scan.hasNext()){ System.out.println(scan.nextLine()); } scan.close(); } } } |
3,基于classpath的数据读取:
package cn..io; import java.io.IOException; import java.util.Scanner; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class Resource2 { public static void main(String[] args) throws IOException { Resource resource=new ClassPathResource("applicationContext.xml"); if(resource.exists()){ Scanner scan=new Scanner(resource.getInputStream()); scan.useDelimiter(" "); while(scan.hasNext()){ System.out.println(scan.nextLine()); } scan.close(); } } } |
发现我们只是改变了一下子类,就可以对不同的资源进行读取,这让程序的开发变得简单和标准化了。
二,ResourceLoalder接口:
从上面的例子可以看到,要对不同的资源进行读取,需要实现Resource不同的子类,但是在Spring中我们要避免new的出现,因此,为了简化Resource读取资源以及操作不同子类实现不同需求,Spring中提供了ResourceLoader接口。
这个接口定义如下:
public interface ResourceLoader { public Resource getResource(String location); public ClassLoader getClassLoader(); } |
可以使用DefaultResourceLoader子类对其进行实例化。在getResource()方法里可以接收一个表示资源路径的字符串数据,这个字符串格式有如下几种:
读取文件系统资源:file:路径;
读取网络资源:http://路径;
package cn..io; import java.io.File; import java.io.IOException; import java.util.Scanner; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; public class Resource4 { public static void main(String[] args) throws IOException { String filePath= "C:" + File.separator + "Users" + File.separator + "Administrator" + File.separator + "Desktop"+File.separator+"pom.xml"; File file=new File(filePath); ResourceLoader loader=new DefaultResourceLoader(); Resource resource=loader.getResource("file:"+filePath); if(resource.exists()){ Scanner scan=new Scanner(resource.getInputStream()); scan.useDelimiter(" "); while(scan.hasNext()){ System.out.println(scan.nextLine()); } scan.close(); } } } |
package cn..io; import java.io.File; import java.io.IOException; import java.util.Scanner; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; public class Resource4 { public static void main(String[] args) throws IOException { ResourceLoader loader=new DefaultResourceLoader(); Resource resource=loader.getResource("http://www.springframework.org/schema/task/spring-task-4.1.xsd"); if(resource.exists()){ Scanner scan=new Scanner(resource.getInputStream()); scan.useDelimiter(" "); while(scan.hasNext()){ System.out.println(scan.nextLine()); } scan.close(); } } } |
package cn..io; import java.io.File; import java.io.IOException; import java.util.Scanner; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; public class Resource4 { public static void main(String[] args) throws IOException { ResourceLoader loader=new DefaultResourceLoader(); Resource resource=loader.getResource("classpath:applicationContext.xml"); if(resource.exists()){ Scanner scan=new Scanner(resource.getInputStream()); scan.useDelimiter(" "); while(scan.hasNext()){ System.out.println(scan.nextLine()); } scan.close(); } } } |
这是可以发现我们只需要以字符串的形式配置不同的路径就能对不同的资源进行读取了。
三,Resource资源的注入:
package cn..util;
import java.io.IOException; import java.util.Scanner;
import org.springframework.core.io.Resource;
public class ResourceUtil { private Resource src;
public void setSrc(Resource src) { this.src = src; } public void print() throws IOException { if (this.src.exists()) { Scanner scan = new Scanner(this.src.getInputStream()); scan.useDelimiter("\n"); while (scan.hasNext()) { System.out.println(scan.nextLine()); } scan.close(); } } } |
2,在applicationContext.xml文件里对资源进行注入控制:
<bean id="resourceUtil" class="cn.wnh.util.ResourceUtil"> <property name="src" value="classpath:applicationContext.xml" /> </bean> |
<bean id="resourceUtil" class="cn.wnh.util.ResourceUtil"> <property name="src" value="http://www.springframework.org/schema/task/spring-task-4.1.xsd" /> </bean> |
public class TestMessage { public static void main(String[] args) throws IOException { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); ResourceUtil ru=ctx.getBean("resourceUtil",ResourceUtil.class); ru.print(); } } |
可以发现,程序里不再需要ResourceLoader了,这个类之间被Spring隐藏起来了。
public class ResourceUtil { private Resource src[]; public void setSrc(Resource src[]){ this.src=src; } public void print() throws IOException{ for(int x=0;x<this.src.length;x++){ if(this.src[x].exists()){ Scanner scan=new Scanner(this.src[x].getInputStream()); scan.useDelimiter("\n"); while(scan.hasNext()){ System.out.println(scan.nextLine()); } scan.close(); } }
} } |
<bean id="resourceUtil" class="cn.wnh.util.ResourceUtil"> <property name="src"> <array> <value>http://www.springframework.org/schema/task/spring-task-4.1.xsd </value> <value>classpath:applicationContext.xml</value> </array> </property> </bean> |
直接执行测试类进行测试,这是可以看到两个文件里的内容都读出来了。
在Resource处理资源的时候考虑到一些复杂资源的定位问题,所以引入了最初Ant工具中提出的通配符的概念,所以支持有以下三种通配符的使用:
<bean id="resourceUtil" class="cn.mldn.util.ResourceUtils"> <property name="src"> <array> <value>classpath:x/**/LICENSE*</value> </array> </property> </bean> |
<bean id="resourceUtil" class="cn.mldn.util.ResourceUtils"> <property name="src"> <array> <value>classpath:**/LICENSE*</value> </array> </property> </bean> |
在定义资源路径的时候可以不受到目录的限制或细小名称的差别的限制。在开发中,最为常见的就是对"*.properties"文件的读取。
以上是关于Spring中对资源的读取支持的主要内容,如果未能解决你的问题,请参考以下文章