Spring中对资源的读取支持

  1. 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();

}

}

,基于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://路径;

classpath读取:classpath:路径;

范例:1,读取文件资源

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();

}

}

}

3,读取classp资源:

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资源的注入:

之前都是直接在程序中配置完成的,但是这样做很明显不可能在实际开发中应用,最好的方式是以字符串的方式通过配置文件实现。现在我们就将所有的路径以字符串的形式在applicationContext文件中进行配置实现不同资源的读取。

1,设置一个专门负责资源处理的程序类:

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文件里对资源进行注入控制:

读取classpath资源:

<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隐藏起来了。

4,实现多个资源的注入:

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>

直接执行测试类进行测试,这是可以看到两个文件里的内容都读出来了。

4,Resource通配符:

在Resource处理资源的时候考虑到一些复杂资源的定位问题,所以引入了最初Ant工具中提出的通配符的概念,所以支持有以下三种通配符的使用:

"?":匹配任意一位字符;

"*":匹配任意多个字符;

"**":匹配任意多级目录的字符串内容。

(1)分别观察下面不同的通配符操作:

<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"文件的读取。

上一篇:C语言:typedef 跟 define 的区别


下一篇:Memcached基础知识