<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>-Flyぁ梦- &#187; 事件驱动</title>
	<atom:link href="http://blog.11034.org/tag/%e4%ba%8b%e4%bb%b6%e9%a9%b1%e5%8a%a8/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.11034.org</link>
	<description></description>
	<lastBuildDate>Sun, 22 Jun 2025 08:59:05 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.2.38</generator>
	<item>
		<title>Tomcat6源码学习</title>
		<link>http://blog.11034.org/2013-05/tomcat6.html</link>
		<comments>http://blog.11034.org/2013-05/tomcat6.html#comments</comments>
		<pubDate>Sun, 19 May 2013 10:27:43 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[ClassLoader]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Servlet]]></category>
		<category><![CDATA[Socket]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[事件驱动]]></category>
		<category><![CDATA[多线程]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[生命周期]]></category>

		<guid isPermaLink="false">http://blog.stariy.org/?p=1803</guid>
		<description><![CDATA[在上一篇博文中说到因为电脑风扇坏了2天于是看完了《How tomcat works》译本，不过这本书是针对To [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>在<a title="小黑风扇坏两天，被逼看完一本书" href="/2013-05/fan_error.html" target="_blank">上一篇博文</a>中说到因为电脑风扇坏了2天于是看完了《How tomcat works》译本，不过这本书是针对Tomcat4和5来讲的比较老了，然后再结合Tomcat6.0.26的源代码调试学习了总共一周的时间，算是大致将Tomcat6.0的一部分工作机制（JSP、JMX、安全管理等模块没研究）给搞清楚了。大概是因为平时基于Java的Web程序写的太多，对Tomcat这一块源码研究特别感兴趣，有时候为了想通一个问题兴奋地吃饭睡觉都在一直想，非常有动力并且也有效率，好久没有这种感觉了。</p>
<p><span id="more-1803"></span>列几点觉得Tomcat设计上比较有意思的地方。</p>
<h2>Connector模块</h2>
<p>Tomcat主要分为Connector模块和Container模块，前者就是处理Socket和HTTP请求，后者是就是常听到的Servlet容器。</p>
<p>Connector模块由于功能比较独立，然后Tomcat内部接口的设计允许第三方组件的使用，就使用了Coyote组件，虽然也是apache下的。有空可以再好好来学习下Coyote的源代码，因为这块涉及了多线程和线程同步、资源优化、效率优化等方面，很值得学习。</p>
<p>Tomcat默认一共占用了3个端口，8080（HTTP/1.1）、8009（AJP/1.3，接受其他服务器转发的请求）和8005（等待SHUTDOWN命令，由Server类在主线程中开启）。其中8080和8009由Connector模块管理，所以默认有2个Connector在运作。</p>
<h2>Container模块</h2>
<p>由Engine、Host、Context、Wrapper四个容器组合而成，分别表示整个引擎、虚拟主机、Web应用、Servlet，通过父子关系连接，然后配套相应的Pipeline和Valve实现过程流。</p>
<h2>Lifecycle接口</h2>
<p>包括启动类（Catalina）、Server、Service、Connector、Container、Executor、Loader、Manager、Realm、Resources、Pipeline都实现了这个接口，通过简单的start()和stop()来递归实现生命周期的管理。</p>
<p>并且这一模块中还用到了LifecycleListener和LifecycleEvent这套事件驱动模型，虽然觉得Tomcat的事件驱动做的比较一般性，注册在某个Lifecycle的LifecycleListener会收到这个Object的所有事件通知，要靠自己去辨别事件类型并作出相应反应，效率较低且定制性弱。</p>
<h2>ClassLoader的设计</h2>
<p>Tomcat为了使类库的私有性，有commonLoader用来加载lib下的jar包，catalinaLoader和sharedLoader分别用来加载Tomcat类库和应用程序共享类库且都以commonLoader为parent。但是在Tomcat6的配置中，默认没有开启catalinaLoader和sharedLoader也没有相应的server和shared目录，导致这3个loader就是同一个commonLoader。这3个loader是StandardClassLoader的实例。</p>
<p>然后对于每一个Web应用程序，都有自己的一个WebappClassLoader，其parent为sharedLoader。这样可以防止不同Web应用程序之间加载互相类库。WebappClassLoader和前面提到的StandardClassLoader都继承自java.net.URLClassLoader，直接从指定目录中读取jar包或class文件。WebappClassLoader直接通过管理Servlet类的字节流来实现Servlet的加载然后缓存。</p>
<p>一般的Servlet只有一个实例，若是实现了STM（SingleThreadModel接口，已Deprecated）的Servlet则会有多个实例缓存着。</p>
<p>但似乎无论怎么设计，都无法避免Web应用程序中的Servlet可以获取到Tomcat启动库中的Bootstrap类（这个包由JVM自带的AppClassLoader加载），默认情况下还可以获取到Tomcat主类库中的所有类（比如Catalina类，因为都是由commonLoader加载，而它又是WebappClassLoader的parent）。尝试过将Tomcat的lib目录中关于Tomcat的类库放到server目录下并配置server.loader属性值（conf/catalina.properties）启动catalinaLoader，这样可以避免Servlet访问到Tomcat主类库，但是这样勉强的同时也阻止了比如ContainerServlet接口（使Servlet能访问Wrapper容器）的运作。</p>
<p>这样的一个坏处就是，可以在Web应用程序的Servlet中获取到Catalina类或者Bootstrap类，再启动一次Tomcat。Servlet中，如果在service方法中这么干会被Tomcat的安全机制给发现使得Tomcat整个关闭，若是配置了loadOnStartup后在init方法中这么干则会引发无限循环导致死机&#8230;</p>
<p>不过通过对Tomcat的ClassLoader的学习，对Java的ClassLoader机制有了大大的实践的了解，无论Tomcat是否真正实现了它设计上的初衷，整个设计思想是值得学习的。</p>
<h2>backgroundProcessor()和后台线程</h2>
<p>Engine容器和Context容器都会通过启动一个后台线程间断执行backgroundProcessor方法，比如重新加载Web应用程序的类文件和资源、扫描Session过期等。</p>
<h2>静态资源</h2>
<p>向Tomcat请求静态资源，和请求Servlet没有太大区别，仍然通过Connector和Container这一流程后，交到Tomcat内部的DefaultServlet来处理读取文件内容并写回客户端，下一次请求会返回304 Not Modified。</p>
<p>所以Tomcat对静态资源的管理比较差速度比较慢，才有apache + tomcat结合的说法吧。</p>
<h4  class="related_post_title">看看 ClassLoader , HTTP , Servlet , Socket , Tomcat , 事件驱动 , 多线程 , 容器 , 生命周期</h4><ul class="related_post"><li>2013-05-20 -- <a target="_blank" href="http://blog.11034.org/2013-05/coyote.html" title="Tomcat的Connector：Coyote">Tomcat的Connector：Coyote</a></li><li>2016-06-08 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_shutdown.html" title="Tomcat监听shutdown释放数据库连接池">Tomcat监听shutdown释放数据库连接池</a></li><li>2016-06-06 -- <a target="_blank" href="http://blog.11034.org/2016-06/tomcat_https.html" title="Tomcat启用https服务">Tomcat启用https服务</a></li><li>2016-03-17 -- <a target="_blank" href="http://blog.11034.org/2016-03/java_client_socket_exceptions.html" title="Java客户端Socket在服务端重启后的异常情况处理">Java客户端Socket在服务端重启后的异常情况处理</a></li><li>2016-03-01 -- <a target="_blank" href="http://blog.11034.org/2016-03/simpledateformat_thread_not_safe.html" title="jdk中SimpleDateFormat的实例线程不安全">jdk中SimpleDateFormat的实例线程不安全</a></li></ul><h4 class="related_post_title">看看 Java </h4><ul class="related_post"><li>2016-09-09 -- <a target="_blank" href="http://blog.11034.org/2016-09/64bits_linux_arena_memory.html" title="64位Linux下Java进程堆外内存迷之64M问题">64位Linux下Java进程堆外内存迷之64M问题</a></li><li>2016-08-18 -- <a target="_blank" href="http://blog.11034.org/2016-08/java_concurrency_in_practice.html" title="读java concurrency in practice">读java concurrency in practice</a></li><li>2016-08-05 -- <a target="_blank" href="http://blog.11034.org/2016-08/thread_stop.html" title="线程清理">线程清理</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/futuretask.html" title="FutureTask简单分析和用法">FutureTask简单分析和用法</a></li><li>2016-06-21 -- <a target="_blank" href="http://blog.11034.org/2016-06/semaphore.html" title="Semaphore简单分析">Semaphore简单分析</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2013-05/tomcat6.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>wordpress发布文章时的Action事件</title>
		<link>http://blog.11034.org/2012-09/wordpress_post_actions.html</link>
		<comments>http://blog.11034.org/2012-09/wordpress_post_actions.html#comments</comments>
		<pubDate>Wed, 26 Sep 2012 13:08:32 +0000</pubDate>
		<dc:creator><![CDATA[-Flyぁ梦-]]></dc:creator>
				<category><![CDATA[Wordpress]]></category>
		<category><![CDATA[Action事件]]></category>
		<category><![CDATA[事件驱动]]></category>

		<guid isPermaLink="false">http://blog.stariy.org/?p=1322</guid>
		<description><![CDATA[昨天一网友加QQ询问关于wp-sns-share对于定时发布文章同步微博失效的问题，然后LZ才知道wordpr [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>昨天一网友加QQ询问关于wp-sns-share对于定时发布文章同步微博失效的问题，然后LZ才知道wordpress还支持定时发布文章文章这一神奇的功能，原来在发布文章的界面点击 “立即发布” 右边的编辑按钮选择一个未来的时间，再点击确定，就变成定时发布了。</p>
<p>wordpress实现定时发布的原理，模拟了一套CRON API，位于/wp-includes/cron.php。程序上并没有真正每分钟都去扫描一次而是在有用户访问的时候才去检测是否到了触发的时间，如果满足触发条件就新发起一个http请求（这样异步的方式不会阻塞原来那次http访问），坏处就是如果完全没有人访问的话，定时就失效啦，而且比较难做到很准时除非每分每秒都有访问量。</p>
<p>为了搞明白wp-sns-share对于定时发布文章同步微博失效的原因，对着wordpress源码调试了很久，顺带着把这块源码摸熟了不少，搞清楚了Action事件这一套路，值得讲一讲。</p>
<p><span id="more-1322"></span></p>
<p>绑定Action的add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1)函数，第四个要注意下，很多Action事件不只一个参数的，这样参数设置好可以在自己的函数里少执行一些数据库操作。</p>
<p>下面列举一些wordpress发布文章中会调用的Action事件，按顺利为：</p>
<p>涉及到的属性值，$post为文章对象，ID为文章ID，文章对象的post_status属性、post_type属性。</p>
<ul>
<li><strong>pre_post_update</strong> : 参数1个（$post_ID）。只要文章已经存在（有了ID）就会被触发，在文章内容被保存前触发。<strong><br />
</strong></li>
<li><strong>transition_post_status</strong> : 参数3个（$new_status, $old_status, $post）。比较通用的一个事件。</li>
<li><strong>{$old_status}_to_{$new_status} </strong>: 参数1个（$post）。比如<strong>future_to_publish</strong>事件可以很好地抓取定时文章发布，<strong>draft_to_publish</strong>事件则是普通文章发布的事件。</li>
<li><strong>{$new_status}_{$post-&gt;post_type} </strong>: 参数2个（$post-&gt;ID, $post）。比如众所周知的<strong>publish_post</strong>事件，这里的组合太多啦。</li>
<li><strong>edit_post </strong>: 参数2个（$post-&gt;ID, $post）。只要文章已经存在（有了ID）就会被触发。</li>
<li><strong>post_updated</strong> : 参数3个（$post_ID, $post_after, $post_before）。只要文章已经存在（有了ID）就会被触发。</li>
<li><strong>save_post</strong> : 参数2个（$post-&gt;ID, $post）。</li>
<li><strong>wp_insert_post</strong> : 参数2个（$post-&gt;ID, $post）。</li>
</ul>
<p>很清楚明了地可以发现，<strong>post_updated</strong>事件是最强大的最万能的，可以获取到最多的参数，包括文章修改前和修改后的所有内容；其次是 <strong>transition_post_status </strong>事件。而<strong>{$old_status}_to_{$new_status} </strong>和 <strong>{$new_status}_{$post-&gt;post_type} </strong>事件的针对性很强大，可以选择某一种特殊情况进行事件抓取。而<strong>edit_post </strong>、<strong>save_post</strong> 、<strong>wp_insert_post </strong>这3个事件就比较鸡肋，基本任何情况都会触发但却很难判断具体是哪种情况，建议不用。</p>
<p>发布、编辑文章的主要代码在/wp-includes/post.php里，主要函数wp_update_post、wp_insert_post等，可以好好看一下。</p>
<p>看源码是最靠谱的，而且也能学习到很多，wordpress的源码真心高深莫测！如果能把wordpress的源码全部看明白了，相信web设计和开发的能力就非常强大了。</p>
<h4  class="related_post_title">看看 Action事件 , 事件驱动</h4><ul class="related_post"><li>2013-05-19 -- <a target="_blank" href="http://blog.11034.org/2013-05/tomcat6.html" title="Tomcat6源码学习">Tomcat6源码学习</a></li></ul><h4 class="related_post_title">看看 Wordpress </h4><ul class="related_post"><li>2014-03-12 -- <a target="_blank" href="http://blog.11034.org/2014-03/new_url_to_template.html" title="wordpress改源码实现自定义URL到自定义页面">wordpress改源码实现自定义URL到自定义页面</a></li><li>2013-12-05 -- <a target="_blank" href="http://blog.11034.org/2013-12/wp-sns-share_2-8.html" title="wp_sns_share更新至2.8，添加小功能">wp_sns_share更新至2.8，添加小功能</a></li><li>2013-02-14 -- <a target="_blank" href="http://blog.11034.org/2013-02/wp_zjuem_in_wordpress.html" title="wp-zjuem，zju cc98表情系统 in wordpress">wp-zjuem，zju cc98表情系统 in wordpress</a></li><li>2012-08-29 -- <a target="_blank" href="http://blog.11034.org/2012-08/wp-sns-share_2-6.html" title="wp_sns_share更新至2.6，增加图片同步">wp_sns_share更新至2.6，增加图片同步</a></li><li>2012-08-16 -- <a target="_blank" href="http://blog.11034.org/2012-08/fuck_renren.html" title="吐槽人人开放平台">吐槽人人开放平台</a></li>]]></content:encoded>
			<wfw:commentRss>http://blog.11034.org/2012-09/wordpress_post_actions.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
