• 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

  • 相关阅读:
    左孩子右兄弟的字典树
    UVA 1401 Remember the Word
    HDOJ 4770 Lights Against Dudely
    UvaLA 3938 "Ray, Pass me the dishes!"
    UVA
    Codeforces 215A A.Sereja and Coat Rack
    Codeforces 215B B.Sereja and Suffixes
    HDU 4788 Hard Disk Drive
    HDU 2095 find your present (2)
    图的连通性问题—学习笔记
  • 原文地址:https://www.cnblogs.com/MattCheng/p/8865287.html
Copyright © 2020-2023  润新知