JPress技术精讲:JPress如何做到安装后重新加载的?

技术

2016-06-16

2599

13

今天在JPress群里问JPress安装完成后,如何能重新加载?  

简单回答下:

1、jetty模式下,JFinal会自动指定检查WebRoot目录,如果有发生变化,会自动重新加载。

2、tomcat容器下,可以通过tomcat的相关配置,让tomcat监控相应的文件,如果发生变化会自动重新加载。

 

下面简要通过代码来看下JFinal在jetty模式下如何做到重新加载的。

 

玩过JFinla的人都知道,JFinal有一个start方法,通过start方法来启动jetty服务,方便开发调试。代码如下:

public static void start(int port) {
		JFinal.start("WebRoot", 8080, "/", 5);
	}

通过JFinal.start方法,传入相关的配置,即可启动jetty。

JFinal的start方法也非常简单,代码如下:

public final class JFinal {
        //....此处省略

        public static void start() {
		server = ServerFactory.getServer();
		server.start();
	}
        //....此处省略

}

通过ServerFactory.getServer()获取一个Server,然后启动Server。这里获取的Server是一个jettyServer。代码如下:

class JettyServer implements IServer {

        // ...此处省略

        public void start() {
		if (!running) {
			try {doStart();} catch (Exception e) {LogKit.error(e.getMessage(), e);}
			running = true;
		}
	}


	private void doStart() {
		// ...此处省略
			Scanner scanner = new Scanner(PathKit.getRootClassPath(), scanIntervalSeconds) {
				public void onChange() {
					try {
						System.err.println("\nLoading changes ......");
						webApp.stop();
						JFinalClassLoader loader = new JFinalClassLoader(webApp, getClassPath());
						webApp.setClassLoader(loader);
						webApp.start();
						System.err.println("Loading complete.");
					} catch (Exception e) {
						System.err.println("Error reconfiguring/restarting webapp after change in watched files");
						LogKit.error(e.getMessage(), e);
					}
				}
			};
			
			scanner.start();
		}
		
		// ...此处省略
	}

        // ...此处省略


}

当Server调用start方法后,start方法会调用doStart()方法,doStart()里面创建了一个扫描器Scanner,传入一个匿名内部类,实现监听onChange监听,并调用Scanner.start()启动Scanner。

Scanner的简要代码如下:

public abstract class Scanner {
        public void start() {
		if (!running) {
			timer = new Timer("JFinal-Scanner", true);
			task = new TimerTask() {public void run() {working();}};
			timer.schedule(task, 1010L * interval, 1010L * interval);
			running = true;
		}
	}


        private void working() {
		scan(rootDir);
		compare();
		
		preScan.clear();
		preScan.putAll(curScan);
		curScan.clear();
	}
	
	private void scan(File file) {
		if (file == null || !file.exists())
			return ;
		
		if (file.isFile()) {
			try {
				curScan.put(file.getCanonicalPath(), new TimeSize(file.lastModified(),file.length()));
			} catch (IOException e) {
				LogKit.error(e.getMessage(), e);
			}
		}
		else if (file.isDirectory()) {
			File[] fs = file.listFiles();
			if (fs != null)
				for (File f : fs)
					scan(f);
		}
	}
	
	private void compare() {
		if (preScan.size() == 0)
			return;
		
		if (!preScan.equals(curScan))
			onChange();
	}


}

当Scanner的start方法被调用的时候,会启动一个定时器执行working()方法,working()方法内部只做两件事情。

1、通过scan方法扫描文件,并把文件的最后修改时间添加到curScan这个map里面去。

2、通过compare方法来判断刚刚扫描的额这个map和之前已经的map是否相同,如果不相同就调用onChange()方法。

 

刚才我们在JettyServer传入了一个匿名内部类,并实现了onChange()方法了,因此,Scanner调用onChange其实就是调用了JettyServer传入的这个匿名内部类的onChange()。

 

再回头来看一下匿名内部类的onChange()的实现:

Scanner scanner = new Scanner(PathKit.getRootClassPath(), scanIntervalSeconds) {
	 public void onChange() {
		try {
			System.err.println("\nLoading changes ......");
			webApp.stop();
			JFinalClassLoader loader = new JFinalClassLoader(webApp, getClassPath());
			webApp.setClassLoader(loader);
			webApp.start();
			System.err.println("Loading complete.");
		} catch (Exception e) {
			System.err.println("Error reconfiguring/restarting webapp after change in watched files");
			LogKit.error(e.getMessage(), e);
		}
	}
};

 

在这里,我们能够很明显的看到,通过webApp.stop方法停止了web服务,然后又通过start()方法启动了web服务。

到此,Jetty环境下讲解完毕。我们也得到了这么一个结论:只要RootClassPath下有文件发生变化,就会造成jetty重新加载,JPress也是利用了JFinal的这个特性,安装完毕后会在ClassPath下创建db.properties文件,发生了文件变化,从而让Jetty达到重新加载的目的。

 

 

发表评论

全部评论:13条

zempty 2016-10-27

这也是maven下安装成功后不能重启的原因!

杨福海 2016-08-13

引用来之于Gavin-King的内容

七牛支持吗?图片服务器,不然扛不住啊!

必须支持啊,支持国内所有云,包括七牛、阿里云、又拍云、腾讯云...

Gavin-King 2016-06-29

七牛支持吗?图片服务器,不然扛不住啊!

sucanber 2016-06-24

测试评论

Adairs 2016-06-22

走过路过 测试飘过

codecly 2016-06-20

不能回复别人的评论

aaamms 2016-06-18

啊啊啊

aaamms 2016-06-18

走过路过 测试飘过

test 2016-06-17

应该是text类型的吧、、、、但是不限长是不是不太好啊。。。

jieyu90 2016-06-16

继续测试

杨福海

世界上最好的语言是Java语言...