Liferay 启动过程分析12-处理全局启动事件

简介:

  在MainServlet中,当初始化扩展环境之后,就开始处理全局启动事件,对应代码是:

 
 
  1.     if (_log.isDebugEnabled()) { 
  2.             _log.debug("Process global startup events"); 
  3.         } 
  4.  
  5.         try { 
  6.             processGlobalStartupEvents(); 
  7.         } 
  8. .. 

 

它会去调用processGlobalStartupEvents()方法:

 
 
  1. protected void processGlobalStartupEvents() throws Exception { 
  2.         EventsProcessorUtil.process( 
  3.             PropsKeys.GLOBAL_STARTUP_EVENTS, PropsValues.GLOBAL_STARTUP_EVENTS); 
  4.     } 

 

我们看下系统是如何处理这些事件的,我们跟进到EventsProcessorUtil类的process方法,它实际传递了2个参数,第一个是字符串 "global.startup.events",第二个参数是字符串形式的事件类数组,它定义在portal.properties文件中:

 
 
  1.    # Global startup event that runs once when the portal initializes. 
  2.    # 
  3.    global.startup.events=com.liferay.portal.events.GlobalStartupAction 

 

而实际处理的process方法在EventsProcessUtil类中,代码如下:

 
 
  1. public static void process(String key, String[] classes) 
  2.         throws ActionException { 
  3.  
  4.         _instance.process(key, classes, nullnullnullnull); 
  5.     } 

 

最终消费它的方法是EventsProcessorUtil类的process()方法:

 
 
  1. public void process( 
  2.             String key, String[] classes, String[] ids, 
  3.             HttpServletRequest request, HttpServletResponse response, 
  4.             HttpSession session) 
  5.         throws ActionException { 
  6.  
  7.         for (String className : classes) { 
  8.             if (Validator.isNull(className)) { 
  9.                 return
  10.             } 
  11.  
  12.             if (_log.isDebugEnabled()) { 
  13.                 _log.debug("Process event " + className); 
  14.             } 
  15.  
  16.             Object event = InstancePool.get(className); 
  17.  
  18.             processEvent(event, ids, request, response, session); 
  19.         } 
  20.  
  21.         if (Validator.isNull(key)) { 
  22.             return
  23.         } 
  24.  
  25.         List<Object> events = _getEvents(key); 
  26.  
  27.         for (Object event : events) { 
  28.             processEvent(event, ids, request, response, session); 
  29.         } 
  30.     } 

 

所以,从第16跟进到InstancePool的_get()方法可以看出,它会去调用参数传递过来的事件类对应的类加载器,让其创建事件类的实例:

 
 
  1. private Object _get(String className, boolean logErrors) { 
  2.         className = className.trim(); 
  3.  
  4.         Object instance = _instances.get(className); 
  5.  
  6.         if (instance == null) { 
  7.             ClassLoader portalClassLoader = 
  8.                 PortalClassLoaderUtil.getClassLoader(); 
  9.  
  10.             try { 
  11.                 Class<?> clazz = portalClassLoader.loadClass(className); 
  12.  
  13.                 instance = clazz.newInstance(); 
  14.  
  15.                 _instances.put(className, instance); 
  16.             } 
  17. .. 

然后会吧这个事件类的实例传递进18行进行处理,我们继续跟进到EventProcessorImpl类的processEvent方法中:

 
 
  1. public void processEvent( 
  2.             Object event, String[] ids, HttpServletRequest request, 
  3.             HttpServletResponse response, HttpSession session) 
  4.         throws ActionException { 
  5.  
  6.         if (event instanceof Action) { 
  7.             Action action = (Action)event; 
  8.  
  9.             try { 
  10.                 action.run(request, response); 
  11.             } 
  12.            ..
  13.         } 
  14.         else if (event instanceof SessionAction) { 
  15.             SessionAction sessionAction = (SessionAction)event; 
  16.  
  17.             try { 
  18.                 sessionAction.run(session); 
  19.             } 
  20.             ..
  21.         } 
  22.         else if (event instanceof SimpleAction) { 
  23.             SimpleAction simpleAction = (SimpleAction)event; 
  24.  
  25.             simpleAction.run(ids); 
  26.         } 
  27.     } 

可以发现,它只是判断事件类型,然后运行这个Action.

 

联系到实际,因为在portal.properties中,我们的事件类型是GlobalStartupAction,它继承自SimpleAction,所以,它运行上述代码的第22-26行,我们跟进到GlobalStartupAction的run方法,发现它做了许多事情:

事情1:插件(layout templates,portlets,themes)的自动部署

事件2:插件的热部署

....

我们这里只对自动部署详细展开说明。

它的代码如下:

 
 
  1. if (PrefsPropsUtil.getBoolean( 
  2.                     PropsKeys.AUTO_DEPLOY_ENABLED, 
  3.                     PropsValues.AUTO_DEPLOY_ENABLED)) { 
  4.  
  5.                 if (_log.isInfoEnabled()) { 
  6.                     _log.info("Registering auto deploy directories"); 
  7.                 } 
  8.  
  9.                 File deployDir = new File( 
  10.                     PrefsPropsUtil.getString( 
  11.                         PropsKeys.AUTO_DEPLOY_DEPLOY_DIR, 
  12.                         PropsValues.AUTO_DEPLOY_DEPLOY_DIR)); 
  13.                 File destDir = new File(DeployUtil.getAutoDeployDestDir()); 
  14.                 long interval = PrefsPropsUtil.getLong( 
  15.                     PropsKeys.AUTO_DEPLOY_INTERVAL, 
  16.                     PropsValues.AUTO_DEPLOY_INTERVAL); 
  17.                 int blacklistThreshold = PrefsPropsUtil.getInteger( 
  18.                     PropsKeys.AUTO_DEPLOY_BLACKLIST_THRESHOLD, 
  19.                     PropsValues.AUTO_DEPLOY_BLACKLIST_THRESHOLD); 
  20.  
  21.                 List<AutoDeployListener> autoDeployListeners = 
  22.                     getAutoDeployListeners(); 
  23.  
  24.                 AutoDeployDir autoDeployDir = new AutoDeployDir( 
  25.                     AutoDeployDir.DEFAULT_NAME, deployDir, destDir, interval, 
  26.                     blacklistThreshold, autoDeployListeners); 
  27.  
  28.                 AutoDeployUtil.registerDir(autoDeployDir); 
  29.             } 
  30.             else { 
  31.             .. 

不难发现,01-03行,它先去查看系统是否开启了自动部署配置,这个配置在portal.properties中,默认是开启的:

 
 
  1.    # Set this to true to enable auto deploy of layout templates, portlets, and 
  2.    # themes. 
  3.    # 
  4.    auto.deploy.enabled=true 

然后它09-12行创建一个File对象指向自动部署目录,13行创建File对象指向部署的目标目录,14-16行获取自动部署的间隔时间,17-19行获取多少次失败就把被部署的插件拖到黑名单的临界值,这些值都可以从portal.properties中获取:

 
 
  1.   # Set the directory to scan for layout templates, portlets, and themes to 
  2.   # auto deploy. 
  3.   # 
  4.   auto.deploy.deploy.dir=${liferay.home}/deploy 
  5.  
  6.   # 
  7.   # Set the directory where auto deployed WARs are copied to. The application 
  8.   # server or servlet container must know to listen on that directory. 
  9.   # Different containers have different hot deploy paths. For example, Tomcat 
  10.   # listens on "${catalina.base}/webapps" whereas JBoss listens on 
  11.   # "${jboss.home.dir}/deploy"Set a blank directory to automatically use the 
  12.   # application server specific directory. 
  13.   # 
  14.   auto.deploy.dest.dir= 
  15.   auto.deploy.default.dest.dir=../webapps 
  16.   auto.deploy.geronimo.dest.dir=${org.apache.geronimo.home.dir}/deploy 
  17.   auto.deploy.glassfish.dest.dir=${com.sun.aas.instanceRoot}/autodeploy 
  18.   auto.deploy.jboss.dest.dir=${jboss.home.dir}/standalone/deployments 
  19.   auto.deploy.jetty.dest.dir=${jetty.home}/webapps 
  20.   auto.deploy.jonas.dest.dir=${jonas.base}/deploy 
  21.   auto.deploy.resin.dest.dir=${resin.home}/webapps 
  22.   auto.deploy.tomcat.dest.dir=${catalina.base}/webapps 
  23.   auto.deploy.weblogic.dest.dir=${env.DOMAIN_HOME}/autodeploy 
  24.  
  25.   # 
  26.   # Set the interval in milliseconds on how often to scan the directory for 
  27.   # changes. 
  28.   # 
  29.   auto.deploy.interval=3000 
  30.  
  31.   # 
  32.   # Set the number of attempts to deploy a file before blacklisting it. 
  33.   # 
  34.   auto.deploy.blacklist.threshold=10 

所以自动部署目录为${liferay_home}/deploy,部署到的位置,如果是tomcat服务器,则是${catalina.base}/webapps,扫描自动部署目录的间隔是3秒,尝试失败直到拉入黑名单的临界次数是10次(第9次失败就拉黑了)

 

然后第21-22行,获取自动部署监听器列表,这些监听器类都配置在portal.properties文件中:

 
 
  1.    # Input a list of comma delimited class names that implement 
  2.    # com.liferay.portal.kernel.deploy.auto.AutoDeployListener. These classes 
  3.    # are used to process the auto deployment of WARs. 
  4.    # 
  5.    auto.deploy.listeners=\ 
  6.        com.liferay.portal.deploy.auto.OSGiAutoDeployListener,\ 
  7.        com.liferay.portal.deploy.auto.ExtAutoDeployListener,\ 
  8.        com.liferay.portal.deploy.auto.HookAutoDeployListener,\ 
  9.        com.liferay.portal.deploy.auto.LayoutTemplateAutoDeployListener,\ 
  10.        com.liferay.portal.deploy.auto.LiferayPackageAutoDeployListener,\ 
  11.        com.liferay.portal.deploy.auto.PortletAutoDeployListener,\ 
  12.        com.liferay.portal.deploy.auto.ThemeAutoDeployListener,\ 
  13.        com.liferay.portal.deploy.auto.WebAutoDeployListener,\ 
  14.        com.liferay.portal.deploy.auto.exploded.tomcat.HookExplodedTomcatListener,\ 
  15.        com.liferay.portal.deploy.auto.exploded.tomcat.LayoutTemplateExplodedTomcatListener,\ 
  16.        com.liferay.portal.deploy.auto.exploded.tomcat.PortletExplodedTomcatListener,\ 
  17.       com.liferay.portal.license.deploy.auto.LicenseAutoDeployListener,com.liferay.portal.deploy.auto.exploded.tomcat.ThemeExplodedTomcatListener 

 

然后第26-28行创建一个AutoDeployDir对象并吧所有的参数都填充进去,最后用工具类注册这个AutoDeployDir,注册的结果就是,用新的线程AutoDeployScanner去扫描自动部署目录,然后一旦发现部署目录有变化,则用相应的AutodeployListener来处理。





本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/907286,如需转载请自行联系原作者

目录
相关文章
【Java集合类面试二十三】、List和Set有什么区别?
List和Set的主要区别在于List是一个有序且允许元素重复的集合,而Set是一个无序且元素不重复的集合。
|
云安全 数据采集 机器学习/深度学习
云安全 | 学习笔记
快速学习云安全,重点介绍了如何在 Linux 下进行安全防护,并从用户系统安全、SSH 安全、恶意文件安全和云安全四个角度诠释如何提升系统的安全性。
云安全 | 学习笔记
|
10月前
|
监控 安全 数据中心
基于Intel RDT平台技术的系统资源隔离能力提升|龙蜥大讲堂103期
龙蜥大讲堂103期探讨了基于Intel RDT平台技术在Koordinator项目NRI模式中提升系统资源隔离能力。课程分为三部分:1) NRI与Koordinator,介绍NRI框架及其应用;2) RDT与Koordinator,讲解RDT技术如何优化资源分配,提高集群效率;3) RDT技术发展,展望未来RDT技术的演进方向及在Koordinator中的集成进展。
202 0
|
缓存 安全 网络协议
Envoy中Wasm Filter相关概念解释
本文旨在介绍Envoy中Wasm Filter相关概念,让用户对相关架构有更加深入的了解,可以快速开发出自己的Wasm插件。 阿里云服务网格(Service Mesh,简称ASM)提供一个全托管式的服务网格平台,兼容社区Istio开源服务网格,用于简化服务的治理,包括服务调用之间的流量路由与拆分管理、服务间通信的认证安全以及网格可观测性能力,从而极大地减轻开发与运维的工作负担。 ASM支持Wasm插件。
674 3
|
运维 负载均衡 算法
“分布式基础概念”全面解析,让你秒懂分布式系统!【一】
该博客文章全面解析了分布式系统的基础概念,包括微服务架构、集群与分布式的区别、节点定义、远程调用、负载均衡、服务注册与发现、配置中心、服务熔断与降级以及API网关,帮助读者快速理解分布式系统的关键组成部分和工作原理。
“分布式基础概念”全面解析,让你秒懂分布式系统!【一】
|
Java API Spring
Spring Boot中使用Feign进行HTTP请求
Spring Boot中使用Feign进行HTTP请求
|
弹性计算 数据安全/隐私保护
阿里云服务器怎么连接?
阿里云服务器怎么连接? 对于不少站长来说,阿里云服务器是必不可少的一个必需品。但是对于不少新手来说,对于服务器却不是那么的了解。今天小编就来为大家介绍下连接阿里云服务器的两种方法。 电脑一台 服务器一台 方法一 首先第一点自然是登录云服务器管理平台,这个自行登录。
15070 1
|
弹性计算 网络安全 数据安全/隐私保护
阿里云服务器新手入门:注册账号、实名认证申请免费云服务器全流程
注册阿里云账号,选择注册方式如密码、扫码或手机号,并完成验证码验证。接着进行实名认证,提供必要个人信息或企业证件。然后,在控制台选择云服务器ECS,点击“免费试用”申请,配置实例并设置登录密码。创建后,通过远程连接工具如SSH登录,开始使用服务器进行软件安装、应用部署等操作。阿里云提供详细文档支持。别忘了点击链接以直接试用。
835 0
|
存储 消息中间件 缓存
聊聊 RocketMQ 主从复制
提到主从复制,我们可能立马会联想到 MySQL 的主从复制。 MySQL 主从复制是 MySQL 高可用机制之一,数据可以从数据库服务器主节点复制到一个或多个从节点。
|
供应链
拥有2000家门店,他如何晋升为服装界的新宠?
—— iwarm3.0加热组件、碳纳米管膜炎、管状石墨结构体...你看到并不是一款高科技电子产品,这是快鱼服饰在这个冬天推出的黑科技产品 - 智能温控羽绒服。 在竞争激烈的服装行业,快鱼(Fast Fish)将“快时尚”的理念推广至全国,建立2000家门店,覆盖浙江、江苏、上海、广东、北京、辽宁、云南和四川等省市,并先后在杭州、虎门、北京、石狮设立大型物流基地。
3649 73