The implementation principle of Java Server hot deployment

Source: Internet
Author: User

Today, I found a note in an elephant note that was previously placed on the Ijavaboy, and is now inaccessible. A few days ago another colleague was discussing the problem. Here to share.


In the process of Web application development or game server development, we are always using hot deployment. The purpose of the thermal deployment is simple to save time for application development and release. For example, we often turn on the hot deployment feature when we develop applications using Tomcat or JBoss application servers. Hot deployment, simply put, we will replace the packaged application directly with the original application, without shutting down or restarting the server, everything is so simple. So how does a hot deployment work? In this article, I'll write an example, which is a container application that allows users to publish their own applications while supporting hot deployment.


in Java, to implement a hot deployment, first you have to understand how classes are loaded in Java. Each application's class is ClassLoader loaded, so to implement an application that supports hot deployment, we can load each user-defined application with a single classloader. Then, when a user-defined application changes, we first destroy the original app and then use a new ClassLoader to load the changed app. All other applications are not subject to a bit of interference. Let's take a look at the design of the application:


with the idea of a general realization, we can think of the following goals to accomplish:
1. Define the interface of a user-defined application, because we need to load the user-defined application in the container application. 2. We also need a profile to allow users to configure their applications. 3, when the application starts, load all existing user custom applications. 4. In order to support hot deployment, we need a listener to listen for changes in each file in the app's publishing directory. This way, when an app is redeployed, we can be notified that the hot-deploy process will take place.
Implementation section:
First, we define an interface in which each user-defined program must contain the only class that implements the interface. The code is as follows:
Public interface IApplication {public        void init ();               public void execute ();               public void Destory ();       }


in this example, each user-defined application must be packaged into a jar file, then published to a specified directory, followed by the specified format, and then, for the first time, the application's configuration should be added to the configuration file. So, first, we need to define a class that can load the specified directory jar file:
        Public ClassLoader Createclassloader (ClassLoader parentclassloader, String ... folders) {              list<url> Jarstoload = new arraylist<url> ();               for (String folder:folders) {                     list<string> jarpaths = scanjarfiles (folder);                      for (String jar:jarpaths) {                            try {                                  file File = new file (jar);                                  Jarstoload.add (File.touri (). Tourl ());                           } catch (Malformedurlexception e) {                                  e.printstacktrace ();}}              }              url[] urls = new url[jarstoload.size ()];              Jarstoload.toarray (URLs);               return new URLClassLoader (URLs, parentclassloader);       }



The simple approach is to scan the jar file from multiple directories and return a new URLClassLoader instance. As for the Scanjarfiles method, you can then download the source code for this article. Then, we need to define a configuration file where the user needs to configure their custom application information here so that the container application then loads all the applications according to this configuration file:
<apps>        <app>               <name> testapplication1</name >               <file> Com.ijavaboy.app.testapplication1</file >        </app>        <app>               <name> Testapplication2</name >               <file> com.ijavaboy.app.testapplication2</file >        </app> </apps>


This configuration is in XML format, each app tag represents an application, each application requires a configuration name and the full path and name of the class that implements the IApplication interface. with this configuration file, we need to parse it, in this case, I am using XStream, very simple, you can download the source code, and then see to know. Skip over here. It's important to mention here: the name of each app is critical, because in this example, our publish directory is the applications directory for the entire project publishing directory, which is the directory where all user-defined applications are published. When a user publishes an application, it is necessary to create a new folder under the directory name that is configured here, and then publish the packaged app to that folder. (You have to do this, otherwise in this case you will publish the failure). Well, now that the method and configuration for loading the jar are there, the following will be the core of the whole example, that is, the application management class, this class is to complete the management and maintenance of each user custom application. The first thing to do is to load an application:
public void CreateApplication (string basepath, AppConfig config) {string folderName = BasePath + globalsettin              G. Jar_folder + Config.getname ();                             ClassLoader loader = This.jarloader. Createclassloader (Applicationmanager. Class.getclassloader (), folderName);                                          try {class<?> Appclass = loader. LoadClass (Config.getfile ());                                          IApplication app = (iapplication) appclass.newinstance ();                                           App.init ();                                   This.apps. Put (Config.getname (), app);              } catch (ClassNotFoundException e) {e.printstacktrace ();              } catch (Instantiationexception e) {e.printstacktrace ();              } catch (Illegalaccessexception e) {e.printstacktrace (); }       }


As you can see, this method receives two parameters, one is the basic path and the other is the application configuration. The basic path is actually the address of the project publishing directory, and AppConfig is actually an entity mapping of the app tag in the configuration file, which loads the specified class from the specified configuration directory, and then invokes the application's Init method to complete the initialization of the user's custom application. Finally, the loaded application is put into memory. now, all the preparations have been done. Next, as the entire application starts, we need to load all the user-defined applications, so we add a method to the Applicationmanager:
        public void Loadallapplications (String basepath) {for                             (AppConfig config:this.configManager.getConfigs ()) {                      This.createapplication (basepath, config);              }       }


This approach is to load all user-configured applications into the container application. OK, now we need to write two separate applications to try the effect, to write this application, we first create a new Java application, then reference the example project, or package The example project into a jar file, and then refer to this separate application, Because in this standalone application, you must include a class that implements the IApplication interface. Let's take a look at the example of a standalone application that looks like this:
public class TestApplication1 implements iapplication{        @Override public        void init () {              System. OUT.PRINTLN ( "Testapplication1-->init");       }        @Override public        Void execute () {              System. Out.println ("testapplication1-->do something");        @Override public        void Destory () {              System. Out.println ("testapplication1-->destoryed");}       }



isn't it simple? Yes, it's that simple. You can do this like this, and then write a separate application. Next, you need to configure it in Applications.xml, which is simply to add the following code to the Apps tab:
        <app>               <name> testapplication1</name >               <file> com.ijavaboy.app.TestApplication1 </file >        </app>


Next, go to the core of this article, then our task, all focused on the heat deployment, in fact, maybe now you still think the hot deployment is very mysterious, but I believe that after a minute, you will not think so. To implement a hot deployment, as we said before, we need a listener to listen to the release directory applications, so that when a jar file for an application changes, we can do hot deployment processing. In fact, to achieve directory file changes in the monitoring, there are many ways, this example I use an Apache open source virtual file system--common-vfs. If you are interested in it, you can visithttp://commons.apache.org/proper/commons-vfs/. Here, we inherit its Filelistener interface to implementfilechangedcan:
        public void Filechanged (Filechangeevent event) throws Exception {              String ext = event.getfile (). GetName (). GetExtension ();               if (! " Jar ". Equalsignorecase (EXT)) {                      return;              }                            String name = Event.getfile (). GetName (). GetParent (). Getbasename ();                            Applicationmanager. GetInstance (). reloadapplication (name);                     }


when a file changes, the method is recalled. So, we called the Applicationmanager Reloadapplication method in this method to reproduce loading the application.
        public void Reloadapplication (String name) {              IApplication Oldapp = this.apps. Remove (name);                             if (Oldapp = = null) {                      return;              }                            Oldapp.destory ();     Call the Destroy method in the user ' s application                            AppConfig config = this.configmanager. GetConfig (name);               if (config = = null) {                      return;              }                            CreateApplication (Getbasepath (), config);       }


when we re-load the application, we first remove the application from memory, then call the original application's Destory method, and then recreate the application instance as it was configured. here, do you still think the hot deployment is very esoteric? Everything is so simple. Well, in order for our custom listener interface to work effectively, we also need to specify the directory it listens to:
public void Initmonitorforchange (String basepath) {try {This.filemanager = Vfs.getmana                                          GER ();                     File File = new file (BasePath + globalsetting.jar_folder);                     FileObject Monitoreddir = This.filemanager. Resolvefile (File.getabsolutepath ());                      Filelistener Filemonitorlistener = new Jarfilechangelistener ();                      This.filemonitor = new Defaultfilemonitor (Filemonitorlistener);                      This.filemonitor. Setrecursive (True);                      This.filemonitor. AddFile (Monitoreddir);                     This.filemonitor. Start (); System.                                   Out.println ("Now to listen" + monitoreddir.getname (). GetPath ());              } catch (Filesystemexception e) {e.printstacktrace (); }       }


here, where the listener is initialized, we use the VFS defaultfilemonitor to complete the listener. And the Listening directory is the application publishing directory applications. Next, in order for the entire application to run continuously without end, we modify the Startup method:
        public static void Main (string[] args) {                            thread t = new Thread (new Runnable () {                                           @Override public                      void Run () {
   applicationmanager manager = Applicationmanager.getinstance ();                           Manager.init ();                     }              });                            T.start ();                             while (true) {                      try {                           Thread. sleep;                     } catch (Interruptedexception e) {                           e.printstacktrace ();                     }              }       }


All right, here we go, it's all over. Now, you already know what it's like to have a hot deployment, right? Don't understand? OK, there is a last move, go to see the source bar!
source I've put it on GitHub, address:Https://github.com/chenjie19891104/ijavaboy/tree/master/AppLoader, Welcome to download use, you have all the right to modify it.
Finally, if there is any place in this article is inaccurate, please correct me, thank you!

The implementation principle of Java Server hot deployment

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.