【JFinal】JFinal中的文件改动后jetty服务器重启动的实现

来源:互联网 发布:淘宝设置满减 编辑:程序博客网 时间:2024/05/16 23:56

参考: JFianl 2.2

用JFianl开发web项目的时候,发现修改文件后会重新启动,感到很好奇,所以研究一下实现的方法

实现的基本步骤

  • 找到项目的根目录
  • 将项目文件中的所有文件的最近修改时间和文件大小在Map中进行保存
  • 通过java的timer定时器保存文件并检查map是否一致
  • 不一致则调用服务器的stop()方法,然后重新初始化服务器,再重新start()

Scanner扫描类

public abstract class Scanner {    //定时器    private Timer timer;    //定时任务    private TimerTask task;    //项目根目录    private File rootDir;    //定时器时间间隔    private int interval;    //是否正在运行    private boolean isRunning;    //准备扫描的文件    //key:文件的完全路径  value:文件的简略表达(最近修改时间+文件大小)    private final Map<String, TimeSize> preScan = new HashMap<String, TimeSize>();    //正在扫描的文件    //key:文件的完全路径  value:文件的简略表达(最近修改时间+文件大小)    private final Map<String, TimeSize> curScan = new HashMap<String, TimeSize>();    //构造器    public Scaner(String rootDir, int interval) {        if (rootDir == null || "".equals(rootDir.trim()))            throw new IllegalArgumentException("根目录不能为空");        this.rootDir = new File(rootDir);        if (!this.rootDir.isDirectory())            throw new IllegalArgumentException("文件夹" + rootDir + "不存在");        if (interval <= 0)            throw new IllegalArgumentException("扫描时隔参数必须大于0");        this.interval = interval;    }    //子类实现的扫描发生改变后的执行动作    public abstract void onChange();    //工作方法,具体的步骤都在这里    private void working() {        //1.首先进行扫描        scan(rootDir);        //2.扫描完成后进行比较,如果有改动则调用onChange()方法        compare();        //3.没有改动则把准备扫描的map清空        preScan.clear();        //4.正在扫描的文件放入        preScan.putAll(curScan);        //5.清空正在扫描文件的map        curScan.clear();    }    //开启扫描,就是建立一个定时任务,执行working()方法    public void start() {        if (!isRunning) {            timer = new Timer("Starlight Scanner", true);            task = new TimerTask() {                @Override                public void run() {                    working();                }};            timer.schedule(task, 1010L * interval, 1010L * interval);            isRunning = true;        }    }    //停止扫描,停止定时器和任务    public void stop() {        if (isRunning) {            timer.cancel();            task.cancel();            isRunning = false;        }    }    //比较的方法,就是将两个map进行equals比较,不一致就说明有文件进行了修改    //出现修改就执行onChange()方法    private void compare() {        if (preScan.size() == 0)            return;        if (!preScan.equals(curScan))            onChange();    }    //递归扫描根目录中所有的文件,将其放入curScan中    private void scan(File file) {        if (file == null || !file.exists())            return;        if (file.isFile()) {            try {                //这里的getCanonicalPath()就是获取文件的完全路径                //TimeSize是一个文件的简略表达的类,可以表示一个文件的,在Scanner类的下方给出了这个类的定义                curScan.put(file.getCanonicalPath(), new TimeSize(file.lastModified(),                                                  file.length()));            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        } else if (file.isDirectory()) {            File[] fs = file.listFiles();            if (fs != null)                for (File f : fs)                    scan(f);        }    }}//此类是文件类的简略表达class TimeSize {    /**      * @fields time 文件的最近修改时间     */     final long time;    /**      * @fields size 文件的大小     */     final long size;    public TimeSize(long time, long size) {        super();        this.time = time;        this.size = size;    }    @Override    public int hashCode() {        return (int)(time ^ size);    }    @Override    public boolean equals(Object obj) {        if (obj instanceof TimeSize) {            TimeSize ts = (TimeSize)obj;            return this.time == ts.time && this.size == ts.size;        }        return false;    }    @Override    public String toString() {        return "TimeSize [time=" + time + ", size=" + size + "]";    }}

JettyServer类

当扫描器发现文件发生变化,就new出一个匿名内部类,执行服务器重启任务

//配置自动扫描if (scanIntervalSeconds > 0) {    Scanner scanner = new Scanner(PathUtil.getWebRootPath(), scanIntervalSeconds) {        @Override        public void onChange() {            System.err.println("\n正在重新加载修改文件...");            try {                webApp.stop();                JFianlClassLoader loader = new JFianlClassLoader(webApp, getClassPath());                webApp.setClassLoader(loader);                webApp.start();                System.err.println("重新加载完成");            } catch (Exception e) {                System.err.println("经过文件的修改后项目无法完成重新配置和重新启动:" + e.getMessage());                //TODO            }        }    };    System.out.println("已完成检查时间为:" + scanIntervalSeconds + "秒的扫描器");    scanner.start();}
原创粉丝点击