ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

深度分析Fileupload是如何删除临时文件的

2021-07-07 10:53:04  阅读:237  来源: 互联网

标签:Fileupload 删除 reaper Tracker deleteStrategy new 临时文件 path final


 

在使用Fileupload组件处理文件上传时,我们可以定义maxInMemorySize,当上传文件大小超过此值,则把文件写入临时文件,防止内存占用过多或溢出。如下配置代码。

 @Bean(name = "multipartResolver")
    public CommonsMultipartResolver multipartResolver() throws IOException {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(1024 * 1024 * maxUploadSize);
        multipartResolver.setDefaultEncoding("utf-8");
        multipartResolver.setUploadTempDir(new FileSystemResource(uploadTempDir));
        multipartResolver.setMaxInMemorySize(maxInMemorySize);
        return multipartResolver;
    }

 

那么当临时文件被服务器端写入到硬盘后是合适删除的呢,下面是FileCleaningTracker的源码,分析了fileupload是如何自动删除文件的。

package org.apache.commons.io;

import java.io.File;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

public class FileCleaningTracker {

    //引用队列,当Reference内关联的对象被GC时会把当前Reference加入到此队列。
    ReferenceQueue<Object> q = new ReferenceQueue<>();
    
	//Tracker继承了PhantomReference(虚引用),内部封装了文件路径。
	//此类负责强引用Tracker,因为Tracker类不能被GC,所以要用引用保存它。
    final Collection<Tracker> trackers = Collections.synchronizedSet(new HashSet<Tracker>()); // synchronized
    
	//删除失败的文件路径集合
    final List<String> deleteFailures = Collections.synchronizedList(new ArrayList<String>());
    
	//指示此类是否完成任务
    volatile boolean exitWhenFinished = false;
    
	//工作线程
    Thread reaper;

	//加入任务,同步方法线程安全
    private synchronized void addTracker(final String path, final Object marker, final FileDeleteStrategy
            deleteStrategy) {
        // synchronized block protects reaper
        if (exitWhenFinished) {
            throw new IllegalStateException("No new trackers can be added once exitWhenFinished() is called");
        }
		
		//工作线程第一次需要初始化,后面看Reaper的解释
        if (reaper == null) {
            reaper = new Reaper();
            reaper.start();
        }
		
		//在trackers集合中加入Tracker对象,Tracker对象包含了path[文件路径],deleteStrategy[删除策略], marker[监控的对象], q[引用队列]
        trackers.add(new Tracker(path, deleteStrategy, marker, q));
    }

	
    public synchronized void exitWhenFinished() {
        // synchronized block protects reaper
        exitWhenFinished = true;
        if (reaper != null) {
            synchronized (reaper) {
                reaper.interrupt();
            }
        }
    }

    //工作线程
    private final class Reaper extends Thread {
        /** Construct a new Reaper */
        Reaper() {
            super("File Reaper");
            setPriority(Thread.MAX_PRIORITY);
            setDaemon(true);
        }

        @Override
        public void run() {
            // thread exits when exitWhenFinished is true and there are no more tracked objects
            while (exitWhenFinished == false || trackers.size() > 0) {
                try {
                    //q.remove()阻塞方法,有对象GC时Tracker会加入到q中,这里可以remove出来。
                    final Tracker tracker = (Tracker) q.remove(); 
					//从set中移除强引用
                    trackers.remove(tracker);
					//删除临时文件
                    if (!tracker.delete()) {
						//删除失败加入记录
                        deleteFailures.add(tracker.getPath());
                    }
					//清楚对象引用
                    tracker.clear();
                } catch (final InterruptedException e) {
                    continue;
                }
            }
        }
    }

	//继承PhantomReference
    private static final class Tracker extends PhantomReference<Object> {

        //文件路径
        private final String path;
        
		//删除策略
        private final FileDeleteStrategy deleteStrategy;

        
        Tracker(final String path, final FileDeleteStrategy deleteStrategy, final Object marker,
                final ReferenceQueue<? super Object> queue) {
            super(marker, queue);
            this.path = path;
            this.deleteStrategy = deleteStrategy == null ? FileDeleteStrategy.NORMAL : deleteStrategy;
        }

        public String getPath() {
            return path;
        }

        //删除临时文件
        public boolean delete() {
            return deleteStrategy.deleteQuietly(new File(path));
        }
    }

}

 

标签:Fileupload,删除,reaper,Tracker,deleteStrategy,new,临时文件,path,final
来源: https://blog.51cto.com/u_11868971/2997573

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有