全部继承 AbstractResource 实现 WritableResource
我们对比分析学习下:
构造器
FileSystemResource
- 重载
- FileSystemResource(File file)
- FileSystemResource(String path)
- 笔记
- FileSystemResource 用了两个成员变量存储,我个人觉得String path这个变量一点用没有,直接File.getPath就可以获得的,何必专门存下来?不理解!
- StringUtils#cleanPath(path) 这个方法很有意思,具体我们可以参考Spring StringUtils#cleanPath method 浅析,
- 这里我们简要说明下流程:
- 首先将“\”全部替换存 “/”
- 然后将前缀(classpath:,file:,xxx)拿出来(如果classpath:/ ,file:/ ,这种也要把”/”一起算到前缀),取出除前缀外的url单独分析
- 按照 “/” ,把url分割数组
- 反向循环,处理”..”,和 “.”这种情况,抵消上一个url节点
- 处理当”..”不能完全抵消时,在url前面添加”..”
- 拼好前缀返回
- 心得
- 主要用来干掉”..”和”.”,但是无法抵消的url则不会干掉(“/a/../../b.xml”最后会变成”/../b.xml”)
- 尽量不使用split(很耗性能),而使用indexOf,substring,springBuilder配合去拼接
- 这里我们简要说明下流程:
- 重载
PathResource
- 重载
- PathResource(Path path)
- PathResource(String path)
- PathResource(URI uri)
- 笔记
- 相对于FileSystemResource,成员变量仅有一个Path path,更节省内存,而且可以兼容URI这种参数
- Path#normalize(),这个方法作用本质上和StringUtils#cleanPath一样,但是对”..”不够抵消,且前缀为”/”时处理不同
- Path#normalize(),对前缀要求严格,必须符合文件系统,类似”file:”,”classpath:”这类的spring前缀则不支持,因此更适合SystemFile,
- 而StringUtils#cleanPath(path),则更适合处理spring中的定义的url!
- 重载
2.有启发的点一览
1. canRead,path.isWritable方法实际上干嘛?为什么要加上 isDirectory等方法判断
因为所谓的canRead和isWritable 实际上判断的是,是否可以有读和写的权限!所有我们必须要判断是否为目录,因为目录尽管有写的权限,但是我们不能写目录!
2. PathResource.getOutputStream ,PathResource.getInputStream 他们为什么要check,而FileSystemResource则不需要!
为什么PathResource这里会加上校验,而FileSystemResource则不需要呢?
其实都需要,而FileSystemResource中,其实FileInputStream在构造器已经校验好了,而 PathResourceFiles中 Files.newInputStream 方法里面没有做校验,所以我们加上校验!
那么为什么要一定要校验,难道没有校验就判断不出来,就不抛异常?
没有校验其实,也可以判断出来,最后仍然抛异常,但是问题在于性能上面,如果我们不做校验,方法就会一直走到开始执行的时候才抛异常,这很影响性能,原理就像我们写log4j的时候会带上 if (log.isDebugEnabled()) 或 if (log.isInfoEnabled())一样
3. 在createRelative方法中
this.path.resolve 和 StringUtils.applyRelativePath(this.path, relativePath)有什么区别
这两个方法作用基本一致,本质上都是在path后面加个fileName,只是返回的对象不同!
这里截取 applyRelativePath 做参考