当前位置: 首页 > 科技观察

热加载和热部署,没听过?看看 Tomcat 是怎么实现的

时间:2023-03-17 14:19:27 科技观察

热加载和热部署,没听说过?看看Tomcat是如何实现的只需重新加载类即可,这个过程不会清除Session。在生产环境中,我们一般采用热部署的方式。还会在Web应用程序的后台线程中定期检测热部署。如果发现任何更改,将重新加载整个Web应用程序。这种方法会更彻底地清除会话。热加载热加载其实在开发过程中经常会用到。比如我们在使用Idea开发的时候,可以在设置页面进行设置。修改文件时,我们可以选择不重启工程,选择重新加载文件。也可以在Tomcat中设置。默认情况下,Tomcat不启用热加载。开启该功能需要在Tomcat路径下的Context.xml中配置reloadable参数。下面演示一下Tomcat是如何热加载的。我们在webapp下新建了一个工程,里面的Servlet文件如下();response.setContentType("text/html;charset=utf-8");out.println(">MyServletVersion1!
");}@OverrideprotectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{System.out.println("MyServlet正在处理post()请求...");PrintWriterout=response.getWriter();response.setContentType("text/html;charset=utf-8");输出。println(">MyServletVersion1!
");}}目录结构如下-webapp--mywebapp--WEB-INF--web.xml--classes--MyServlet.class为演示tomcat运行时可以动态修改和加载class文件,我们分为以下三个步骤来st艺术Tomcat正常。输入http://localhost:8080/mywebapp/myservlet,观察页面输出。Tomcat启动时,修改MyServlet文件,覆盖原来的class文件。再次观察页面情况。观察页面的输出是否被修改。下面用动态图演示一下效果更直观。我们可以看到,在Tomcat运行的时候,直接替换class文件就可以直接生效了。那么Tomcat是怎么做到的呢?其实我们可以自己推导。所有类文件都由类加载管理。如果改了class文件,是不是只需要更换对应的类加载器,重新加载就可以了?那么我们来验证一下我们的结论,看看如何在Tomcat中实现hot。加载。Tomcat应该启动一个新的线程来监视类文件是否发生变化。然后可以看到在Context的启动方法中,可以看到调用了threadStart方法。protectedvoidthreadStart(){backgroundProcessorFuture=Container.getService(this).getServer().getUtilityExecutor().scheduleWithFixedDelay(newContainerBackgroundProcessor(),//要执行的RunnablebackgroundProcessorDelay,//第一次执行延迟多长时间backgroundProcessorDelay,//每次执行后interval多久执行一次TimeUnit.SECONDS);//时间单位}}周期任务在后台启动,使用Java提供的ScheduledThreadPoolExecutor。除了周期性执行任务外,它还有线程池的作用。上面代码中调用了scheduleWithFixedDelay方法,传入的第一个参数就是要执行的任务。让我们看看任务类ContainerBackgroundProcessor是如何实现的。protectedclassContainerBackgroundProcessorimplementsRunnable{@Overridepublicvoidrun(){//注意这里传入的参数是“宿主类”processChildren(ContainerBase.this);}protectedvoidprocessChildren(Containercontainer){try{//1.调用当前容器的backgroundProcess方法。container.backgroundProcess();//2.遍历所有子容器,递归调用processChildren,//这样就会处理当前容器的子孙Container[]children=container.findChildren();for(inti=0;i