java.net.URL 类可用于访问带有各种URL前缀的资源,但是对于访问一些资源还是不够方便。比如不能从类路径或者相对于ServletContext来获取资源。而Spring 的Resource接口,则可以通过类路径等方式来访问资源。
1 Resource接口
图 Resource接口及方法
getInputStream | 定位并打开资源,返回一个输入流。 |
exists | 判断资源是否存在。 |
isOpen | 判断输入流是否打开,如果打开,则不能多次读取。 |
getDescription | 通常返回资源的完全限定名或URL,常用于在报错时使用。 |
表 Resource的部分方法
2 Resource 的实现
UrlResource | 用于需要通过URL访问的资源。 |
ClassPathResource | 用于需要通过类路径访问的资源。可用当前线程的类加载器、给定的类加载器及给定的类来获取资源。 |
FileSystemResource | 是java.io.File及java.nio.file.Path的资源实现。支持作为文件和URL的解析。 相对于java到File类,该类没有太大优势,File类也可以访问文件系统资源。 |
ServletContextResource | 用于在ServletContext中获取资源。是以web项目的根目录作为相对路径。 |
InputStreamResource | 通过给定InputStream输入流来获取资源。只有在没有特定资源实现时才应使用它。尽可能使用ByteArrayResource或其他Resource实现来替换。 与其他Resource实现类相比,这是已打开的输入流(其构造函数参数是一个Resource),如果需要将资源描述符保存在某处或者需要多次读取流,请不要使用它。 |
ByteArrayResource | 通过给定字节流来获取资源。 |
表 Resource的实现类
注意:打包时,类文件里的其他文件(除.java文件外)会被忽略,需要将文件复制到resources文件夹下。
public class ResourceImpl {public static void main(String[] args) throws IOException {classPathResource();fileSystemResource();urlResource();inputStreamResource();}private static void urlResource() throws IOException {UrlResource urlResource = new UrlResource("file:/Users/huangzaizai/Desktop/huangmingfu/code/spring_resource/src/main/resources/article/res.properties");showPropertiesValue(urlResource.getInputStream(), "urlResource");}private static void classPathResource() throws IOException {ClassPathResource classPathResource = new ClassPathResource("res.properties", ResourceImpl.class);showPropertiesValue(classPathResource.getInputStream(),"classPathResource");}private static InputStream fileSystemResource() throws IOException {FileSystemResource fileSystemResource = new FileSystemResource("/Users/huangzaizai/Desktop/huangmingfu/code/spring_resource/src/main/resources/article/res.properties");showPropertiesValue(fileSystemResource.getInputStream(),"fileSystemResource");return fileSystemResource.getInputStream();}private static void inputStreamResource() throws IOException {InputStreamResource inputStreamResource = new InputStreamResource(fileSystemResource());showPropertiesValue(inputStreamResource.getInputStream(),"inputStreamResource");}private static void showPropertiesValue(InputStream stream,String type) throws IOException {Properties properties = new Properties();properties.load(stream);System.out.println(type + ":" + properties.getProperty("textValue"));}
}
2.1 ResourceLoader
public interface ResourceLoader {Resource getResource(String location);
}
Resource 接口是用来根据路径来获取资源的。所有的ApplicationContext实现类都实现了这个接口。如果传入带有特定前缀的路径来获取特定类型的资源。或者根据ApplicationContext类型来获取特定类型的资源。例如ClassPathXmlApplicationContext 的getResource 方法如果传入的路径没有特定的前缀,则获取是ClassPathResource资源。
前缀 | 例子 | 描述 |
classpath: | classpath:com/app/config.xml | 从类路径加载。 |
file: | file:///data/config/xml | 从系统文件加载,作为URL方式。 |
http: | https://baidu.com/logo.png | 从网络上获取资源。 |
没有前缀 | /data/config.xml | 根据ApplicationContext类型来决定获取资源的方式。 |
表 路径部分前缀
2.2 ResourceLoaderAware 接口
public interface ResourceLoaderAware {void setResourceLoader(ResourceLoader resourceLoader);
}
当一个bean 实现了这个接口时,可以用来设置ResourceLoader。也可以通过@Autowired 的方式自动注入ResourceLoader 实例。
2.3 作为依赖
Resource的类型的变量可以像其他类型一样被自动注入,在设置值时(value属性),只要设置对应的资源路径即可。
3 ApplicationContext及资源路径
在创建一个ApplicationContext实例时,通常使用资源路径的字符串(或者字符串数组)来作为其构造函数的参数,例如XML配置文件。
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
也可以使用带有特殊前缀资源路径来作为构造函数的参数:
ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
3.1 通配符
在使用字符串路径时,可以使用通配符。但是资源一次只指向一个资源。
classpath*:packageName 表示所有能匹配上packageName类路径的资源。