任务:做一个合同文件证据下载的组件。
细节:
- 一个合同有多个类型的文件,一个类型中可能会存在多个文件。
- 需要提供不同的接口,有时候下载一个,有时候全部下载
- 不同的证据类型,下载的方式不一样。
系统设计:
- 最开始设计系统的时候,设计的比较简单。就是使用工厂模式给不同的类型设计了不同的下载方式。直接返回了String filename. Byte[] content.的一个list。如果要取一个呢,就使用list.get(0),如果使用全部就遍历
- 但是这样有明显的缺点
- 所有的文件都copy到内存一遍。
- 无论你需要多少个文件,我都需要全部取出来。
- 但是这样有明显的缺点
- 修改第二版,就是返回一个String filename, InputStream resouce。
- 优点
- 不会再往内存copy一遍文件内容。可以减少内存使用,减少gc次数。
- 这样也有缺点
- 无论最后需要多少个文件,都需要先得到对应的Inputstream,会在资源商造成浪费。
- 再次修改想法,其实就是想传入一个Function<String, Stream>.这样就可以使用的时候再调用。
- 优点
- 修改第三版,返回一个中间状态的结果。String key, Type storeType。然后后续在通过一个工厂方法,把这个结果集返回成inputStream。
- 优点
- 减少对系统的压力,在不必要的时候不获取inputstream
- 代码整洁,避免了返回list和getOne两种逻辑不通。最大化代码重用。
- 缺点
- 在使用InputStream的时候,要切记close。如果通过http直接返回了这个inputStream,那么就可以不用关闭。Springboot会帮你关闭。否则就需要自己关闭。自己试了一下,重复关闭不会造成任何问题。那么自己copy完成后就要手动关闭。这里面会把input传递几次,所以不适合使用try-with –resource方式关闭。这部分需要认真仔细。修改的第二版代码也会面临这个问题。
- 其实也造成了代码的复杂,需要通过两个工厂方法,一个返回中间状态,一个返回最终状态
- TODO:
- 优点
其实有考虑把第二个工厂方法,放到中间状态的bean中。直接调用bean的方法返回最后的结果。这样更加面向对象一些。最后没有做。还是因为这样处理比较少。