Spring 使用介绍(三)—— 资源
一、Resource接口
Spring提供Resource接口,代表底层外部资源,提供对底层外部资源的一致性访问接口
public interface InputStreamSource { InputStream getInputStream() throws IOException; }
public interface Resource extends InputStreamSource { boolean exists(); boolean isReadable(); boolean isOpen(); URL getURL() throws IOException; URI getURI() throws IOException; File getFile() throws IOException; long contentLength() throws IOException; long lastModified() throws IOException; Resource createRelative(String relativePath) throws IOException; String getFilename(); String getDescription(); }
二、内置Resource实现
1、ByteArrayResource byte[]数组资源
2、FileSystemResource 文件系统资源
3、ClassPathResource classpath路径资源
4、UrlResource URL资源
- http: new UrlResource(“http://地址”)
- ftp: new UrlResource(“ftp://地址”)
- file: new UrlResource(“file:d:/test.txt”)
5、ServletContextResource 代表web应用资源,简化servlet容器的ServletContext接口的getResource操作和getResourceAsStream操作
public class ResourceTest { private static void dumpStream(Resource resource) throws Exception { if (resource.exists()) { InputStream is = resource.getInputStream(); byte[] bytes = new byte[is.available()]; is.read(bytes); System.out.println(new String(bytes)); } } public static void main(String[] args) throws Exception { // byte[]数组资源 Resource resource = new ByteArrayResource("hello world".getBytes()); // 文件系统资源 //Resource resource = new FileSystemResource("D:\\hello.txt"); // classpath路径资源 //Resource resource = new ClassPathResource("durid.properties"); // URL资源 //Resource resource = new ClassPathResource("file:D:\\hello.txt"); dumpStream(resource); System.out.println(resource.getURL()); } }
三、ResourceLoader接口
ResourceLoader接口返回Resource,可作为生产Resource的工厂类
public interface ResourceLoader { Resource getResource(String location); ClassLoader getClassLoader(); }
1、ResourceLoader接口实现类:DefaultResourceLoader 通过前缀指定要加载的资源,不指定默认加载classpath资源
-
- classpath:path 表示返回ClasspathResource
- http://path 或 file:path 表示返回UrlResource资源
public static void main(String[] args) throws Exception { DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); Resource resource = resourceLoader.getResource("file:D:\\hello.txt"); dumpStream(resource); System.out.println(resource.getURL()); }
2、ResourceLoader注入
Spring提供ResourceLoaderAware接口,用于通过ApplicationContext上下文注入ResourceLoader,ResourceLoaderAware是一个标记接口
public interface ResourceLoaderAware { void setResourceLoader(ResourceLoader resourceLoader); }
定义实现类,并实例化为bean
public class ResourceBean implements ResourceLoaderAware { private ResourceLoader resourceLoader; @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } public ResourceLoader getResourceLoader() { return this.resourceLoader; } }
<bean class="cn.matt.resource.ResourceBean"></bean>
Spring检测到该接口,会将ApplicationContext注入进去
public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml"); ResourceBean resourceBean = context.getBean(ResourceBean.class); System.out.println(resourceBean.getResourceLoader().getClass().getName() ); }
该方式属侵入性,推荐使用自动注入方式(ApplicationContext已实现ResourceLoader ,可根据类型自动注入)
四、ResourcePatternResolver接口
1、Ant路径通配符
Ant路径通配符支持?、*、**:
?:匹配一个字符,如“config?.xml”将匹配“config1.xml”;
*:匹配零个或多个字符串,如“cn/*/config.xml”将匹配“cn/javass/config.xml”,但不匹配匹配“cn/config.xml”;而“cn/config-*.xml”将匹配“cn/config-dao.xml”;
**:匹配路径中的零个或多个目录,如“cn/**/config.xml”将匹配“cn /config.xml”,也匹配“cn/javass/spring/config.xml”;
而“cn/javass/config-**.xml”将匹配“cn/javass/config-dao.xml”,即把“**”当做两个“*”处理。
Spring提供AntPathMatcher来进行Ant风格的路径匹配
public class AntPathMatcherTest { private PathMatcher pathMatcher = new AntPathMatcher(); @Test public void testQuestionMark() { Assert.assertTrue(pathMatcher.match("config?.xml", "config1.xml")); Assert.assertFalse(pathMatcher.match("config?.xml", "config.xml")); } @Test public void testOneAsterisk() { Assert.assertTrue(pathMatcher.match("config-*.xml", "config-dao.xml")); Assert.assertTrue(pathMatcher.match("config-*.xml", "config-.xml")); Assert.assertTrue(pathMatcher.match("config-**.xml", "config-dao.xml")); Assert.assertTrue(pathMatcher.match("/cn/*/config.xml", "/cn/javass/config.xml")); Assert.assertFalse(pathMatcher.match("/cn/*/config.xml", "/cn/config.xml")); } @Test public void testTwoAsterisk() { Assert.assertTrue(pathMatcher.match("/cn/**/config-*.xml", "/cn/javass/config-dao.xml")); Assert.assertTrue(pathMatcher.match("/cn/**/config-*.xml", "/cn/javass/spring/config-dao.xml")); Assert.assertTrue(pathMatcher.match("/cn/**/config-*.xml", "/cn/config-dao.xml")); } }
2、ResourcePatternResolver接口定义
public interface ResourcePatternResolver extends ResourceLoader { String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; Resource[] getResources(String locationPattern) throws IOException; }
ResourcePatternResolver接口继承自ResourceLoader
PathMatchingResourcePatternResolver为其实现类,默认通过AntPathMatcher进行路径匹配,除支持‘classpath’外,还支持‘classpath*’
1)classpath
a、包含通配符时,可匹配当前项目的多个资源,但无法匹配依赖包中的资源
b、无通配符时,可匹配依赖包中的资源,且仅能匹配一个资源
@Test public void testResourcePatternResolver() throws IOException { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); // 路径包含通配符时,只能匹配当前项目中的资源,但无法匹配依赖包中的资源 Resource[] resources = resolver.getResources("classpath:META-INF/*.txt"); Assert.assertTrue(resources.length == 2); Resource[] resources2 = resolver.getResources("classpath:META-INF/*.schemas"); Assert.assertTrue(resources2.length == 0); // 路径无通配符时,可匹配依赖包中的资源 Resource[] resources3 = resolver.getResources("classpath:META-INF/spring.schemas"); Assert.assertTrue(resources3.length == 1);
// 路径无通配符时,仅能匹配一个资源
Resource[] resources4 = resolver.getResources("classpath:META-INF/license.txt");
Assert.assertTrue(resources4.length == 1); // 路径包含通配符时,通配符前必须指定搜索目录,才能匹配到资源 Resource[] resources5 = resolver.getResources("classpath:*.xml"); Assert.assertTrue(resources5.length == 0);
}
以上示例程序运行的资源目录结构如下:
resource(当前项目)
|---- spring-context.xml
|---- META-INF
|---- license.txt
|---- license2.txt
spring-beans-4.2.5.RELEASE.jar(依赖包)
|---- META-INF
|---- spring.schemas
|---- license.txt
注意:ResourceLoader.getResource()接口不支持通配符(无论DefaultResourceLoader、PathMatchingResourcePatternResolver)
@Test public void testResourceLoader() throws IOException { ResourceLoader resourceLoader = new PathMatchingResourcePatternResolver(); // 存在 Resource resource = resourceLoader.getResource("classpath:META-INF/license.txt"); Assert.assertTrue(resource.exists()); // 不存在 Resource resource2 = resourceLoader.getResource("classpath:META-INF/*.txt"); Assert.assertFalse(resource2.exists()); }
2)classpath*
'classpath*'可加载当前项目及依赖包下的所有匹配的资源
@Test public void testResourcePatternResolver2() throws IOException { ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] resources = resolver.getResources("classpath*:**/*.xml"); Assert.assertTrue(resources.length > 1); }
3)file:加载一个或多个文件系统中的Resource,如“file:D:/*.txt”
4)AppliacationContext继承自ResourcePatternResolver,其实现类的构造方法内部使用PathMatchingResourcePatternResolver,因而支持通配符
ApplicationContext context = new ClassPathXmlApplicationContext("spring-*.xml");
AppliacationContext的实现类:
ClassPathXmlApplicationContext 不指定前缀将返回默认的ClassPathResource资源,否则将根据前缀来加载资源
FileSystemXmlApplicationContext 不指定前缀将返回FileSystemResource,否则将根据前缀来加载资源
WebApplicationContext:不指定前缀将返回ServletContextResource,否则将根据前缀来加载资源
五、注入Resource
1、单个资源
Spring提供了ResourceEditor(继承自PropertyEditor ),用于在注入的字符串和Resource之间进行转换
2、多个资源
Spring提供了ResourceArrayPropertyEditor(继承自PropertyEditor ),用于在注入的字符串和Resource[]之间进行转换
public class Hello { // 单个资源 private Resource resource; // 多个资源 private Resource[] resources; public Resource getResource() { return resource; } public void setResource(Resource resource) { this.resource = resource; } public Resource[] getResources() { return resources; } public void setResources(Resource[] resources) { this.resources = resources; } }
<bean class="cn.matt.resource.Hello"> <property name="resource" value="classpath:test.xml" /> <property name="resources" value="classpath*:**/*.xml" /> </bean>
@Test public void testResourceInjection() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml"); Hello hello = context.getBean(Hello.class); // 单个资源 Resource resource = hello.getResource(); Assert.assertTrue(resource.exists()); // 多个资源 Resource[] resources = hello.getResources(); Assert.assertTrue(resources.length > 1); }
参考:
第四章 资源 之 4.1 基础知识 ——跟我学spring3
第四章 资源 之 4.2 内置Resource实现 ——跟我学spring3
第四章 资源 之 4.3 访问Resource ——跟我学spring3
第四章 资源 之 4.4 Resource通配符路径 ——跟我学spring3