commons-fileupload 简单梳理

DisFileItemFactory

继承了FileItemFactory接口,并且并且重写了FileItemFactory的唯一方法public FileItem createItem(String fieldName, String contentType, boolean isFormField, String fileName)该方法会对HTTP的主体内容进行封装,并提供了一系列配置方法,如内存存储数的阀值sizeThreshold,临时文件存储目录repository,还有默认的数据编码defaultCharset

ServletFileUplad

ServletFileUpload主要是将HttpServletRequest封装ServletRequestContext传给FileUpload处理,ServletRequestContext是个装饰者模式,不过装饰一下HttpServletRequest的getContentType方法,getContentLength方法,getCharacterEncoding方法,在1.4的版本中,我们还看到ServletRequestContext继承了UploadContext接口,该接口只有一个contentLength方法,ServletRequestContext重新该方法,用于获取HTTP消息头上Content-length的值,而官方认为HttpServletRequest.getContentLength()方法获取的值不标准,至少返回的类型是int的话,并不够用,所以新增了UploadContext接口来修复这个bug,返回long类型值。而这个UploadContext的接口,官方说明是会在2.0的时候去掉,并将contentLength重命名成新的方法名到RequestContext中。

FileUploadBase.parseRequest(RequestContext)
遍历迭代FileItemIterator,将存放在FileItemlterator的里面的FileItemStream拿出来,封装到FileItemFactory所提供FileItem,再将FileItem存放到集合中,返回出去,需要注意的是,在遍历FileItemIterator过程中,出现异常的情况下,所有的FileItem中的临时文件会立即删除。

FileItemIterator

FileItemIterator的业务,交给了继承FileItemIteratorUploadFileBase.FileItemIteratorImpl实现进行处理,FileItemIterator就相当于解析文本体的控制层,用于控制MultipartStream的读取操作。

MultipartStream

MultipartStream是用于读取 主体文本,受FileItemIterator的控制,当调用FileItemIteratorImpl.findNextItem()就会使得MultipartStream解析封装下一个参数内容。因为 主体文本是用content-type的boundary进行分割的,MutlipartStream使用KMP算法计算出boundary的前缀表进行查找。

主体文本的组成就是分割线+参数内容,所以我们要准确地读取到参数内容,需要确定好分割线的起始位置,分割线的长度。但是在读取过程,因为主体文本一般都比较大,只能通过一个缓存区buffer来分段读取,也就造成了一个问题,无法确定那里是分割线,因为buffer有可能完全将分割线的字节读取了,也有可能只读取了分割线的部分字节,也有可能完全没有读取到分割线的字节,所以MultipartStream定义了三个成员变量:buffer读取的开始位置head,buffer读取的最后一个位置tail,还有保留分割线字节数pad,在读取buffer的数据时,以head作为开始读取的游标,以tail做为读取buffer的结束位置,而pad,会在buffer中没有找到分割线时候,保留buffer的最后pad个的字节,在下一次的从主体内容的流中读取到buffer的时候,会先将原buffer中最后pad个字节放到buffer的前面,再填充剩下的buffer字节,从而精确的读到参数内容。

FileCleaningTracker

FileCleaningTracker是一个文件清理的跟踪器。而他不是简单的通过定时器来定时清理文件,而是使用跟踪GC来清理文件,我觉得这个方法很优秀,因为通过GC跟踪比起定时器,更加少占用cpu的资源时间,也是能保证FileCleaningTracker能够像GC一样,根据服务器的情况做出相关处理,而不是。
主要看addTracker(String,marker,FileDeleteStrategy)根据参数,封装到Tracker中,并将Trecker添加到Trackers中。Reaper是个线程,懒汉式去初始化了Reaper,Reaper是个守护线程,用于根据GC的回收情况去删除临时文件,当删除文件不成功时,会将会将删除失败的临时文件路径添加到delteFailures中.
Tracker继承了PhantomReference,PhantomReference是java中的虚引用,主要用于跟踪GC的回收情况,需要跟ReferenceQueue连用,当GC回收对象PhantomReference的referent时,会先将对象放进ReferenceQueue队列中,我们可以同ReferenceQueue.remove()方法,使得referent出栈,然后GC会在下一次回收对象的时候,查看referent是否还有被引用,没有就直接清理掉.

DeferredFileOutputStream

DeferredFileOutputStream是一个根据设定的最大内存阀值去控制写入到内存中,还是写入到硬盘中。
当达到阀值的时候,thresholdReached()就会被调用,会将内存流memoryOutputStream中的数据转换到写入硬盘的流FileOuputStream中,并将FileOuputStream重新赋值currentOuptputStream

你可能感兴趣的:(commons-fileupload 简单梳理)