﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-空白</title><link>http://www.blogjava.net/niumd/</link><description>天行健、君子以自强不息 ；地势坤、君子以厚德载物……</description><language>zh-cn</language><lastBuildDate>Tue, 28 Apr 2026 21:37:35 GMT</lastBuildDate><pubDate>Tue, 28 Apr 2026 21:37:35 GMT</pubDate><ttl>60</ttl><item><title>Spring JDBC Framework详解——批量JDBC操作、ORM映射</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349965.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 13:06:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349965.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349965.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349965.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349965.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">作者：niumd，转载请注明出处，谢谢&nbsp;&nbsp;&nbsp;</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-size: small;" style="font-size: small; "><span lang="EN-US"><span mce_style="font-size: x-small;" style="font-size: x-small; ">发表时间：2010 年&nbsp;03 月&nbsp;17 日&nbsp;&nbsp;</span></span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span lang="EN-US"><span mce_style="font-size: small;" style="font-size: small; "><span mce_style="font-size: x-small;" style="font-size: x-small; ">原文链接：<a href="http://ari.iteye.com/admin/blogs/618449" mce_href="/admin/blogs/618449">http://ari.iteye.com/admin/blogs/618449</a></span></span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>一、Spring JDBC 概述</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; Spring 提供了一个强有力的模板类JdbcTemplate简化JDBC操作，DataSource,JdbcTemplate都可以以Bean的方式定义在想xml配置文件，JdbcTemplate创建只需注入一个DataSource，应用程序Dao层只需要继承JdbcDaoSupport, 或者注入JdbcTemplate，便可以获取JdbcTemplate，JdbcTemplate是一个线程安全的类，多个Dao可以注入一个JdbcTemplate；</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="xml" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">&lt;!--         Oracle数据源           --&gt;
&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;
&lt;property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/&gt;
&lt;property name="url" value="jdbc:oracle:thin:@oracle.devcake.co.uk:1521:INTL"/&gt;
&lt;property name="username" value="sa"/&gt;
&lt;property name="password" value=""/&gt;
&lt;/bean&gt;
&lt;bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"&gt;
&lt;property name="dataSource" ref="dataSource"/&gt;
&lt;/bean&gt;
&lt;!--  set注入方式获取jdbcTemplate --&gt;
&lt;bean id="customerDao" class="JdbcCustomerDao" &gt;
&lt;property name="jdbcTemplate" ref="jdbcTemplate"/&gt;
&lt;/bean&gt;
&lt;!-- 注入dataSource，customerDao通过继承JdbcDaoSupport ,使用this.getJdbcTemplate()获取JdbcTemplate   --&gt;
&lt;bean id="customerDao" class="JdbcCustomerDao" &gt;
&lt;property name="dataSource" ref="dataSource"/&gt;
&lt;/bean&gt;
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">然后将jdbcTemplate对象注入自定义的Dao、或者继承JdbcDaoSupport，例如：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">public class JdbcCustomerDao extends JdbcDaoSupport implements CustomerDao {
}
public class JdbcCustomerDao implements CustomerDao {
private JdbcTemplate jdbcTemplate
public void setJdbcTemplate()JdbcTemplate jdbcTemplate{
this.jdbcTemplate=jdbcTemplate
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>二、&nbsp;JdbcTemplate 提供以下主要方法简化JDBC操作：</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>2.1、List query(String sql,Ojbect[] args,RowMapper rowMapper)</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; 说明：常用的查询，sql待执行的sql语句，args是sql语句的参数，rowMapper负责将每一行记录转化为java对象存放在list，并最终返回，例如：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">public List&lt;Book&gt; queryByAuthor(String author) {
String sql = "select * from book where author=?";
Collection c = getJdoTemplate().find(sql,
new Object[] { author },new BookRowMapper());
List&lt;Book&gt; books = new ArrayList&lt;Book&gt;();
books.addAll(c);
return books;
}
class BookRowMapper implements RowMapper{
public Object mapRow(ResultSet res, int index) throws SQLException {
Book book = new Book();
book.setId(rs.getInt("id"));
//省略set
return book；
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 更新、删除、其他查询操作类似，举例如下，详细细节请参考spring api：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">//返回值为一个长整形
public long getAverageAge() {
return getJdbcTemplate().queryForLong("SELECT AVG(age) FROM employee");
}
//返回一个整数
public int getTotalNumberOfEmployees() {
return getJdbcTemplate().queryForInt("SELECT COUNT(0) FROM employees");
}
//更新操作
this.jdbcTemplate.update(
"insert into t_actor (first_name, surname) values (?, ?)",
new Object[] {"Leonor", "Watling"});
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;2.<strong>2、spring 2.5新功能，另类的jdbc ORM：BeanPropertyRowMapper</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面我们检索时必须实现RowMapper，将结果集转化为java对象。Spring2.5 简化了这一操作，使得我们不必再实现RowMapper，实现此功能的俩个神奇东东便是：ParameterizedRowMapper，ParameterizedBeanPropertyRowMapper，貌似通过java反射机制实现了将resultset字段映射到java对象，但是数据表的列必须和java对象的属性对应，没有研究源码，有点类似于apache 的BeanUtil，不知为何这部分在spring开发参考手册没有，难道不是经典。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">//使用ParameterizedBeanPropertyRowMapper
@SuppressWarnings({"unchecked"})
public List&lt;Customer&gt; getAll() {
return getJdbcTemplate().query("select * from t_customer", ParameterizedBeanPropertyRowMapper.newInstance(Customer.class));
}
//使用BeanPropertyRowMapper
@SuppressWarnings({"unchecked"})
public List&lt;Customer&gt; getAll() {
return getJdbcTemplate().query("select * from t_customer", new BeanPropertyRowMapper(Customer.class));
}
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">注意：ParameterizedBeanPropertyRowMapper是BeanPropertyRowMapper子类。另外表的字段名称必须和实体类的成员变量名称一致；</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>2.3、spring之JDBC批量操作</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span mce_style="font-family: Courier New;" style="font-family: 'Courier New'; ">jdbcTemplate.batchUpdate(final String[] sql) ，API解释：Issue multiple SQL updates on a single JDBC Statement using batching，翻译过来大致为：解决多个sql的插入、更新、删除操作在一个Statement中。性能一般。</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-family: Courier New;" style="font-family: 'Courier New'; ">&nbsp;&nbsp;&nbsp;jdbcTemplate.batchUpdate(String sql, final BatchPreparedStatementSetter pss),类似于JDBC的PreparedStatement，性能较上着有所提高。</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-family: Courier New;" style="font-family: 'Courier New'; ">&nbsp;&nbsp;&nbsp;我们举例说明如何使用，示例如下:</span></p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">final int count = 2000;
final List&lt;String&gt; firstNames = new ArrayList&lt;String&gt;(count);
final List&lt;String&gt; lastNames = new ArrayList&lt;String&gt;(count);
for (int i = 0; i &lt; count; i++) {
firstNames.add("First Name " + i);
lastNames.add("Last Name " + i);
}
jdbcTemplate.batchUpdate(
"insert into customer (id, first_name, last_name, last_login, comments) values (?, ?, ?, ?, ?)",
new BatchPreparedStatementSetter() {
//为prepared statement设置参数。这个方法将在整个过程中被调用的次数
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setLong(1, i + 10);
ps.setString(2, firstNames.get(i));
ps.setString(3, lastNames.get(i));
ps.setNull(4, Types.TIMESTAMP);
ps.setNull(5, Types.CLOB);
}
//返回更新的结果集条数
public int getBatchSize() {
return count;
}
});
}
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-family: Courier New;" style="font-family: 'Courier New'; ">&nbsp; BatchSqlUpdate类是SqlUpdate 的子类，适用于插入、删除、更新批量操作，内部使用PreparedStatement，所以效率很高，批量语句达到设定的batchSize，或者手动调用flush才会执行批量操作。注意：此类是非线程安全的，必须为每个使用者创建一个实例，或者在同一个线程中使用前调用reset。</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-family: Courier New;" style="font-family: 'Courier New'; ">&nbsp;&nbsp; 下面我们举例说明如何使用BatchSqlUpdate，来执行批量操作。示例如下：</span></p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">class BatchInsert extends BatchSqlUpdate {
private static final String SQL = "insert into t_customer (id, first_name, last_name, last_login, "
+ "comments) values (?, ?, ?, ?, null)";
BatchInsert(DataSource dataSource) {
super(dataSource, SQL);
declareParameter(new SqlParameter(Types.INTEGER));
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.TIMESTAMP));
setBatchSize(10);
}
}
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">int count = 5000;
for (int i = 0; i &lt; count; i++) {
batchInsert.update(new Object[] { i + 100L, "a" + i, "b" + i, null });
}
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;至此，spring JDBC主要的应用基本上都简单罗列一番，所有代码均为文章举例，不是很严谨，仅为演示每一种用法，抛砖引玉，希望有独特见解的拍砖，有问题的请指明问题所在,谢谢</p>
</div>
<img src ="http://www.blogjava.net/niumd/aggbug/349965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 21:06 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat6.x目录与server.xml详解</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349964.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 13:04:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349964.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349964.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349964.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349964.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349964.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本文参考自：Tomcat全攻略参考链接：http://www.ibm.com/developerworks/cn/java/l-tomcat/index.html#1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Tomcat&nbsp;服务器是一个免费的开放源代码的Web&nbsp;应用服务器，目前最新版本是6.x，相对5.x性能提升很多，主要...&nbsp;&nbsp;<a href='http://www.blogjava.net/niumd/archive/2011/05/10/349964.html'>阅读全文</a><img src ="http://www.blogjava.net/niumd/aggbug/349964.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 21:04 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349964.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>项目重构之命令模式</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349962.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 13:03:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349962.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349962.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349962.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349962.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349962.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; &nbsp; 项目中有个业务处理类大小117K，代码2700行，看此类差点雷死我，如今如要增加业务逻辑大约20个吧，此类如果随着项目工程的二期、三期如次添加逻辑迟早有一天大小达到M，噢、mygod。细心研读前人的工作总结，发现其中有点可改造的蛛丝马迹(本人很笨、别笑我才发现如何改造)。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; 下面我们对业务流程、以及涉及的相关类进行介绍，<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">Msg</span>代表接受到客户端的一个消息报文，消息报文结构：消息头<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">+</span></span>消息体，消息头参数固定、消息体参数不定，下面是一个简单的类图，这只是一个模拟场景，<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">****Req</span></span>代表各户端请求类，<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">***Rsp</span></span>代表返回给客户端的参数类。实际比此复杂，为描述问题我们简单摘除几个类介绍，别问我为何这么设计继承。类图<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">msg</span></span>与<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">msgHead</span></span>是组合关系也许画错了、不当之处请指出，勿恶语向伤；</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span lang="EN-US">&nbsp;</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/264052/9e823571-e81c-35d0-a4e5-b5b14b525542.png" mce_src="http://dl.iteye.com/upload/attachment/264052/9e823571-e81c-35d0-a4e5-b5b14b525542.png" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /><br />
&nbsp;处理请求Handler类的代码逻辑如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">//类中主要方法如下
public void execute(Object object) {
Message message = (Message)object;
int opcode = message.getOpcode();
int connectId = message.getConnectId();
//消息头已经解析，获取消息体，即子类属性字节数组
byte[] bytes = message.getBytes();
if (opcode == MsgInfo.ADD_RING) {
// 订购彩铃
orderRing(connectId, bytes);
} else if (opcode == MsgInfo.PRESENT_RING) {
// 赠送彩铃
presentRing(connectId, bytes);
} else if (opcode == MsgInfo.DEL_RING) {
// 删除个人铃音
delPersonalRing(connectId, bytes);
}
//此处省略n个else if
}
//其他删除、赠送与省略的else if中的处理逻辑与之基本相同
private void orderRing(int connectId, byte[] bytes) {
//处理方法分为四步，具体代码省略
//1、解析字节数组为订购铃音类
//2、处理订购关系
//3、处理结果封装为订购响应类
//4、发送回客户端
}
//省略presentRing、delPersonalRing等一系列其他方法，所有的处理方法参数相同&#8230;&#8230;
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;鉴于此、想到使用命令模式改造此类，如果不了解命令模式请阅读相关书籍，大话设计模式或设计与模式，这里我们仅给出大致的定于与类图。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">何谓命令模式：将一个请求封装为一个对象，从而是你可用不同的请求对客户端参数化，对请求排队或记录日志，以及支持可撤销的操作。</p>
<p class="MsoNormal" mce_style="text-indent: 15.75pt; margin: 0cm 0cm 0pt;" style="margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; text-indent: 15.75pt; ">&nbsp;<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">Shit</span></span>、这句话很难理解哦，那就先别理解了，我们看下命令模式的类图，然后介绍如何使用命令模式改造上面的<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">elseif</span></span>。</p>
<p class="MsoNormal" mce_style="text-indent: 21pt; margin: 0cm 0cm 0pt;" style="margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; text-indent: 21pt; ">类图先省略，上班偷空写的；</p>
<p class="MsoNormal" mce_style="text-indent: 21pt; margin: 0cm 0cm 0pt;" style="margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; text-indent: 21pt; "><span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">&nbsp;</span></span></p>
<p class="MsoNormal" mce_style="text-indent: 21pt; margin: 0cm 0cm 0pt;" style="margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; text-indent: 21pt; ">下面进入正题，对<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">Handler</span></span>小手术开始，主要考虑如下：</p>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong><span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">1、</span></span>提炼方法</strong></p>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; 将每个<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">if</span></span>语句块中的逻辑提取为一个方法，这里我们的<span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">handler</span></span>已经实现，就是：<span mce_style="font-family: 'Courier New'; color: black; font-size: 10pt;" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">orderRing</span>、<span mce_style="font-family: 'Courier New'; color: black; font-size: 10pt;" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">presentRing</span>、<span mce_style="font-family: 'Courier New'; color: black; font-size: 10pt;" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">delPersonalRing</span>、&#8230;&#8230;。</p>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong><span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">2、</span></span>提炼类</strong></p>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; 将每个业务处理方法提取为以各类，然后对具体类进行抽象，提取父类或者接口；代码如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">public Abstract class Command{
public void execute()
｝
public class OrderRingCommand extends Command {
private Handler hander;
public OrderRingCommand(Handler hander){
this.hander = hander;
}
public void execute(int connectId, byte[] bytes){
//1、解析字节数组为订购铃音类
//2、增加订购关系
//3、处理结果封装为订购响应类
//4、发送回客户端
}
/**
* 1、解析字节数组为订购铃音类
*/
public void method1(){
}
/**
* 2、处理订购关系
*/
public void method2(){
}
/**
* 3、处理结果封装为订购响应类
*/
public void method3(){
}
/**
* 4、结果发送回客户端
*/
public void method4(){
}
}
public class DelRingCommand extends Command {
private Handler hander;
public DelRingCommand(Handler hander){
this.hander = hander;
}
public void execute(int connectId, byte[] bytes){
//1、解析字节数组为订购铃音类
//2、删除购关系
//3、处理结果封装为订购响应类
//4、发送回客户端
}
//提取方法
}
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; ">&nbsp;</span></span></span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong><span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; ">3、</span></span>命令模式改造替换</strong><span lang="EN-US"><span mce_style="font-family: Calibri;" style="font-family: Calibri; "><strong>elseif：</strong></span></span></p>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">Map&lt;Integer, Command&gt; map = new HashMap&lt;Integer,Command&gt;();
static{
map.put(MsgInfo.ADD_RING, new OrderRingCommand());
//省却其他，这里仅为演示，实际项目中实例化类通过spring容器或者其他方法
}
public void execute(Object object) {
Message message = (Message)object;
int opcode = message.getOpcode();
int connectId = message.getConnectId();
//消息头已经解析，获取消息体，即子类属性字节数组
byte[] bytes = message.getBytes();
map.get(opcode).execute(connectId,bytes);
}
</pre>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "></span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span lang="EN-US"></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "></span></span></span></span></span></span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span lang="EN-US"></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span lang="EN-US">&nbsp;命令模式替换else if代码坏味道的重构结束，众多的if条件块烟消云散，取而代之的是一个个精简的类，doc版本在附件中</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span lang="EN-US"><font><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><font mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "></font></span></span></span></span></span></span></font></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font><font mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><br />
</font></font></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p>&nbsp;</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p>&nbsp;</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "><span mce_style="font-size: 10.5pt;" style="font-size: 10.5pt; "></span></span></span></span></span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p class="MsoListParagraph" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
</div>
<img src ="http://www.blogjava.net/niumd/aggbug/349962.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 21:03 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349962.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入浅出ThreadLocal</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349961.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 13:02:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349961.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349961.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349961.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349961.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349961.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>一、ThreadLocal概述</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 学习JDK中的类，首先看下JDK API对此类的描述，描述如下：</p>
<div class="quote_title" style="font-weight: bold; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; margin-top: 5px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; ">JDK API 写道</div>
<div class="quote_div" style="border-left-color: #cccccc; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; ">该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物，因为访问某个变量（通过其 get 或 set 方法）的每个线程都有自己的局部变量，它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段，它们希望将状态与某一个线程（例如，用户 ID 或事务 ID）相关联。&nbsp;<br />
<br />
</div>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;API表达了下面几种观点：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">1、ThreadLocal不是线程，是线程的一个变量，你可以先简单理解为线程类的属性变量。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">2、ThreadLocal 在类中通常定义为静态类变量。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">3、每个线程有自己的一个ThreadLocal，它是变量的一个&#8216;拷贝&#8217;，修改它不影响其他线程。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 既然定义为类变量，为何为每个线程维护一个副本（姑且成为&#8216;拷贝&#8217;容易理解），让每个线程独立访问？多线程编程的经验告诉我们，对于线程共享资源（你可以理解为属性），资源是否被所有线程共享，也就是说这个资源被一个线程修改是否影响另一个线程的运行，如果影响我们需要使用synchronized同步，让线程顺序访问。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; ThreadLocal适用于资源共享但不需要维护状态的情况，也就是一个线程对资源的修改，不影响另一个线程的运行；这种设计是<strong>&#8216;空间换时间&#8217;</strong>，synchronized顺序执行是<strong>&#8216;时间换取空间&#8217;</strong>。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>二、ThreadLocal方法介绍</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<table border="1" cellspacing="0" cellpadding="3" width="100%">
    <tbody>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>&nbsp;<a title="ThreadLocal 中的类型参数" href="http://ari.iteye.com/java/lang/ThreadLocal.html" mce_href="/java/lang/ThreadLocal.html">T</a></code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/java/lang/ThreadLocal.html#get()" mce_href="/java/lang/ThreadLocal.html#get()">get</a></strong>()</code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;返回此线程局部变量的当前线程副本中的值。</td>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>protected &nbsp;<a title="ThreadLocal 中的类型参数" href="http://ari.iteye.com/java/lang/ThreadLocal.html" mce_href="/java/lang/ThreadLocal.html">T</a></code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/java/lang/ThreadLocal.html#initialValue()" mce_href="/java/lang/ThreadLocal.html#initialValue()">initialValue</a></strong>()</code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;返回此线程局部变量的当前线程的&#8220;初始值&#8221;。</td>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>&nbsp;void</code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/java/lang/ThreadLocal.html#remove()" mce_href="/java/lang/ThreadLocal.html#remove()">remove</a></strong>()</code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;移除此线程局部变量当前线程的值。</td>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>&nbsp;void</code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/java/lang/ThreadLocal.html#set(T)" mce_href="/java/lang/ThreadLocal.html#set(T)">set</a></strong>(<a title="ThreadLocal 中的类型参数" href="http://ari.iteye.com/java/lang/ThreadLocal.html" mce_href="/java/lang/ThreadLocal.html">T</a>&nbsp;value)</code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;将此线程局部变量的当前线程副本中的值设置为指定值。</td>
        </tr>
    </tbody>
</table>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>三、深入源码</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; ThreadLocal有一个ThreadLocalMap静态内部类，你可以简单理解为一个MAP，这个&#8216;Map&#8217;为每个线程复制一个变量的&#8216;拷贝&#8217;存储其中。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 当线程调用ThreadLocal.get()方法获取变量时,首先获取当前线程引用，以此为key去获取响应的ThreadLocalMap，如果此&#8216;Map&#8217;不存在则初始化一个，否则返回其中的变量，代码如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="get方法" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; "> public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;调用get方法如果此Map不存在首先初始化，创建此map，将线程为key，初始化的vlaue存入其中，注意此处的initialValue，我们可以覆盖此方法，在首次调用时初始化一个适当的值。setInitialValue代码如下：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">    private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; set方法相对比较简单如果理解以上俩个方法，获取当前线程的引用，从map中获取该线程对应的map，如果map存在更新缓存值，否则创建并存储，代码如下：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">    public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 对于ThreadLocal在何处存储变量副本，我们看getMap方法：获取的是当前线程的ThreadLocal类型的threadLocals属性。显然变量副本存储在每一个线程中。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">/**
* 获取线程的ThreadLocalMap 属性实例
*/
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 上面我们知道变量副本存放于何处，这里我们简单说下如何被java的垃圾收集机制收集，当我们不在使用是调用set(null)，此时不在将引用指向该&#8216;map&#8217;，而线程退出时会执行资源回收操作，将申请的资源进行回收，其实就是将属性的引用设置为null。这时已经不在有任何引用指向该map，故而会被垃圾收集。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp;四、ThreadLocal应用示例</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在我的另一篇文章，对ThreadLocal的使用做了一个实例，此示例也可以用作生产环境，请参见：<a href="http://ari.iteye.com/blog/757641" mce_href="/blog/757641">http://ari.iteye.com/blog/757641</a></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">如有问题请留言讨论，谢谢</p>
</div>
<img src ="http://www.blogjava.net/niumd/aggbug/349961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 21:02 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ThreadLocal示例</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349960.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 13:01:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349960.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349960.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349960.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349960.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349960.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; &nbsp; 本文借花献佛，引用Tim Cull的博文&#8220;SimpleDateFormat: Performance Pig&#8221;介绍下ThreadLocal的简单使用，同时也对SimpleDateFormat的使用有个深入的了解。</p>
<div class="quote_title" style="font-weight: bold; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; margin-top: 5px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; ">Tim Cull 写道</div>
<div class="quote_div" style="border-left-color: #cccccc; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; ">Just yesterday I came across this problem &#8220;in the wild&#8221; for the third time in my career so far: an application with performance problems creating tons of java.text.SimpleDateFormat instances. So, I have to get this out there: creating a new instance of SimpleDateFormat is incredibly expensive and should be minimized. In the case that prompted this post, I was using JProfiler to profile this code that parses a CSV file and discovered that 50% of the time it took to suck in the file and make 55,000 objects out of it was spent solely in the constructor of SimpleDateFormat. It created and then threw away a new one every time it had to parse a date. Whew!&nbsp;<br />
<br />
&#8220;Great,&#8221; you think, &#8220;I&#8217;ll just create one, static instance, slap it in a field in a DateUtils helper class and life will be good.&#8221;&nbsp;<br />
<br />
Well, more precisely, life will be good about 97% of the time. A few days after you roll that code into production you&#8217;ll discover the second cool fact that&#8217;s good to know: SimpleDateFormat is not thread safe. Your code will work just fine most of the time and all of your regression tests will probably pass, but once your system gets under a production load you&#8217;ll see the occasional exception.&nbsp;<br />
<br />
&#8220;Fine,&#8221; you think, &#8220;I&#8217;ll just slap a &#8217;synchronized&#8217; around my use of that one, static instance.&#8221;&nbsp;<br />
<br />
Ok, fine, you could do that and you&#8217;d be more or less ok, but the problem is that you&#8217;ve now taken a very common operation (date formatting and parsing) and crammed all of your otherwise-lovely, super-parallel application through a single pipe to get it done.</div>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; 大致意思：Tim Cull碰到一个SimpleDateFormat带来的严重的性能问题，该问题主要有SimpleDateFormat引发，创建一个SimpleDateFormat实例的开销比较昂贵，解析字符串时间时频繁创建生命周期短暂的实例导致性能低下。即使将SimpleDateFormat定义为静态类变量，貌似能解决这个问题，但是SimpleDateFormat是非线程安全的，同样存在问题，如果用&#8216;synchronized&#8217;线程同步同样面临问题，同步导致性能下降（线程之间序列化的获取SimpleDateFormat实例）。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; Tim Cull使用Threadlocal解决了此问题，对于每个线程SimpleDateFormat不存在影响他们之间协作的状态，为每个线程创建一个SimpleDateFormat变量的拷贝或者叫做副本，代码如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 使用ThreadLocal以空间换时间解决SimpleDateFormat线程安全问题。
* @author
*
*/
public class DateUtil {
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
@SuppressWarnings("rawtypes")
private static ThreadLocal threadLocal = new ThreadLocal() {
protected synchronized Object initialValue() {
return new SimpleDateFormat(DATE_FORMAT);
}
};
public static DateFormat getDateFormat() {
return (DateFormat) threadLocal.get();
}
public static Date parse(String textDate) throws ParseException {
return getDateFormat().parse(textDate);
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;创建一个ThreadLocal类变量，这里创建时用了一个匿名类，覆盖了initialValue方法，主要作用是创建时初始化实例。也可以采用下面方式创建；</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">//第一次调用get将返回null
private static ThreadLocal threadLocal = new ThreadLocal()；
//获取线程的变量副本，如果不覆盖initialValue，第一次get返回null，故需要初始化一个SimpleDateFormat，并set到threadLocal中
public static DateFormat getDateFormat()
{
DateFormat df = (DateFormat) threadLocal.get();
if(df==null){
df = new SimpleDateFormat(DATE_FORMAT)
threadLocal.set(df);
}
return df;
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 我们看下我们覆盖的initialValue方法：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">protected T initialValue() {
return null;//直接返回null
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
</div>
<img src ="http://www.blogjava.net/niumd/aggbug/349960.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 21:01 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349960.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>探究Struts2运行机制：StrutsPrepareAndExecuteFilter 源码剖析</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349959.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 12:58:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349959.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349959.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349959.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349959.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349959.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp; 作者：niumd</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp;&nbsp;blog：<a href="http://ari.iteye.com/" mce_href="/">http://ari.iteye.com</a></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp;一、概述</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; Struts2的核心是一个Filter，Action可以脱离web容器，那么是什么让http请求和action关联在一起的，下面我们深入源码来分析下Struts2是如何工作的。</p>
<div class="quote_title" style="font-weight: bold; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; margin-top: 5px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; ">FilterDispatcher API 写道</div>
<div class="quote_div" style="border-left-color: #cccccc; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; ">Deprecated. Since Struts 2.1.3, use StrutsPrepareAndExecuteFilter instead or StrutsPrepareFilter and StrutsExecuteFilter if needing using the ActionContextCleanUp filter in addition to this one</div>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;鉴于常规情况官方推荐使用StrutsPrepareAndExecuteFilter替代FilterDispatcher，我们此文将剖析StrutsPrepareAndExecuteFilter，其在工程中作为一个Filter配置在web.xml中，配置如下：</p>
<pre name="code" class="xml" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">&lt;filter&gt;
&lt;filter-name&gt;struts2&lt;/filter-name&gt;
&lt;filter-class&gt;org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;struts2&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>二、源码属性方法简介</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 下面我们研究下StrutsPrepareAndExecuteFilter源码，类的主要信息如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<table border="1" cellspacing="0" cellpadding="3" width="100%">
    <tbody>
        <tr class="TableHeadingColor">
            <th colspan="2" align="left"><strong>属性摘要</strong></th>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>protected &nbsp;<a title="class or interface in java.util" href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/List.html?is-external=true" mce_href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/List.html?is-external=true">List</a>&lt;<a title="class or interface in java.util.regex" href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html?is-external=true" mce_href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html?is-external=true">Pattern</a>&gt;</code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#excludedPatterns" mce_href="/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#excludedPatterns">excludedPatterns</a></strong></code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>protected &nbsp;<a title="class in org.apache.struts2.dispatcher.ng" href="http://ari.iteye.com/org/apache/struts2/dispatcher/ng/ExecuteOperations.html" mce_href="/org/apache/struts2/dispatcher/ng/ExecuteOperations.html">ExecuteOperations</a></code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#execute" mce_href="/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#execute">execute</a></strong></code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>protected &nbsp;<a title="class in org.apache.struts2.dispatcher.ng" href="http://ari.iteye.com/org/apache/struts2/dispatcher/ng/PrepareOperations.html" mce_href="/org/apache/struts2/dispatcher/ng/PrepareOperations.html">PrepareOperations</a></code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#prepare" mce_href="/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#prepare">prepare</a></strong></code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
        </tr>
    </tbody>
</table>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; StrutsPrepareAndExecuteFilter与普通的Filter并无区别，方法除继承自Filter外，仅有一个回调方法，第三部分我们将按照Filter方法调用顺序，由init—&gt;doFilter—&gt;destroy顺序地分析源码。</p>
<table border="1" cellspacing="0" cellpadding="3" width="100%">
    <tbody>
        <tr class="TableHeadingColor">
            <th colspan="2" align="left"><strong>方法摘要</strong></th>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>&nbsp;void</code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#destroy()" mce_href="/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#destroy()">destroy</a></strong>()</code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;继承自Filter，用于资源释放</td>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>&nbsp;void</code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#doFilter(javax.servlet.ServletRequest,%20javax.servlet.ServletResponse,%20javax.servlet.FilterChain)" mce_href="/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#doFilter(javax.servlet.ServletRequest,%20javax.servlet.ServletResponse,%20javax.servlet.FilterChain)">doFilter</a></strong>(<a title="class or interface in javax.servlet" href="http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletRequest.html?is-external=true" mce_href="http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletRequest.html?is-external=true">ServletRequest</a>&nbsp;req,&nbsp;<a title="class or interface in javax.servlet" href="http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletResponse.html?is-external=true" mce_href="http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletResponse.html?is-external=true">ServletResponse</a>&nbsp;res,&nbsp;<a title="class or interface in javax.servlet" href="http://java.sun.com/javaee/5/docs/api/javax/servlet/FilterChain.html?is-external=true" mce_href="http://java.sun.com/javaee/5/docs/api/javax/servlet/FilterChain.html?is-external=true">FilterChain</a>&nbsp;chain)</code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;继承自Filter，执行方法</td>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>&nbsp;void</code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#init(javax.servlet.FilterConfig)" mce_href="/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#init(javax.servlet.FilterConfig)">init</a></strong>(<a title="class or interface in javax.servlet" href="http://java.sun.com/javaee/5/docs/api/javax/servlet/FilterConfig.html?is-external=true" mce_href="http://java.sun.com/javaee/5/docs/api/javax/servlet/FilterConfig.html?is-external=true">FilterConfig</a>&nbsp;filterConfig)</code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;继承自Filter，初始化参数</td>
        </tr>
        <tr class="TableRowColor">
            <td width="1%" align="right" valign="top" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code>protected &nbsp;void</code></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><code><strong><a href="http://ari.iteye.com/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#postInit(org.apache.struts2.dispatcher.Dispatcher,%20javax.servlet.FilterConfig)" mce_href="/org/apache/struts2/dispatcher/ng/filter/StrutsPrepareAndExecuteFilter.html#postInit(org.apache.struts2.dispatcher.Dispatcher,%20javax.servlet.FilterConfig)">postInit</a></strong>(<a title="class in org.apache.struts2.dispatcher" href="http://ari.iteye.com/org/apache/struts2/dispatcher/Dispatcher.html" mce_href="/org/apache/struts2/dispatcher/Dispatcher.html">Dispatcher</a>&nbsp;dispatcher,&nbsp;<a title="class or interface in javax.servlet" href="http://java.sun.com/javaee/5/docs/api/javax/servlet/FilterConfig.html?is-external=true" mce_href="http://java.sun.com/javaee/5/docs/api/javax/servlet/FilterConfig.html?is-external=true">FilterConfig</a>&nbsp;filterConfig)</code>&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Callback for post initialization（一个空的方法，用于方法回调初始化）</td>
        </tr>
    </tbody>
</table>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>三、源码剖析&nbsp;&nbsp;&nbsp;&nbsp;</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;<strong>1、init方法</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init是Filter第一个运行的方法，我们看下struts2的核心Filter在调用init方法初始化时做哪些工作：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; "> public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
try {
//封装filterConfig，其中有个主要方法getInitParameterNames将参数名字以String格式存储在List中
FilterHostConfig config = new FilterHostConfig(filterConfig);
// 初始化struts内部日志
init.initLogging(config);
//<strong>创建dispatcher ，并初始化，这部分下面我们重点分析，初始化时加载那些资源</strong>
Dispatcher dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
//初始化类属性：prepare 、execute
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
//回调空的postInit方法
postInit(dispatcher, filterConfig);
} finally {
init.cleanup();
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 首先看下FilterHostConfig ，源码如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">public class FilterHostConfig implements HostConfig {
private FilterConfig config;
/**
*构造函数
*/
public FilterHostConfig(FilterConfig config) {
this.config = config;
}
/**
*  根据init-param配置的param-name获取param-value的值
*/
public String getInitParameter(String key) {
return config.getInitParameter(key);
}
/**
*  返回初始化参数名的List
*/
public Iterator&lt;String&gt; getInitParameterNames() {
return MakeIterator.convert(config.getInitParameterNames());
}
public ServletContext getServletContext() {
return config.getServletContext();
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 只有短短的几行代码，getInitParameterNames是这个类的核心，将Filter初始化参数名称有枚举类型转为Iterator。此类的主要作为是对filterConfig 封装。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;<strong><span mce_style="color: #ff0000;" style="color: #ff0000; ">&nbsp;重点来了，创建并初始化Dispatcher</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; "> public Dispatcher initDispatcher( HostConfig filterConfig ) {
Dispatcher dispatcher = createDispatcher(filterConfig);
dispatcher.init();
return dispatcher;
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; 创建Dispatcher，会读取 filterConfig 中的配置信息，将配置信息解析出来，封装成为一个Map，然后根绝servlet上下文和参数Map构造Dispatcher ：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">private Dispatcher createDispatcher( HostConfig filterConfig ) {
Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
for ( Iterator e = filterConfig.getInitParameterNames(); e.hasNext(); ) {
String name = (String) e.next();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
}
return new Dispatcher(filterConfig.getServletContext(), params);
}
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; Dispatcher初始化，加载struts2的相关配置文件，将按照顺序逐一加载：default.properties，struts-default.xml,struts-plugin.xml,struts.xml，&#8230;&#8230;</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">/**
*初始化过程中依次加载如下配置文件
*/
public void init() {
if (configurationManager == null) {
configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
try {
//加载org/apache/struts2/default.properties
init_DefaultProperties(); // [1]
//加载struts-default.xml,struts-plugin.xml,struts.xml
init_TraditionalXmlConfigurations(); // [2]
init_LegacyStrutsProperties(); // [3]
//用户自己实现的ConfigurationProviders类
init_CustomConfigurationProviders(); // [5]
//Filter的初始化参数
init_FilterInitParameters() ; // [6]
init_AliasStandardObjects() ; // [7]
Container container = init_PreloadConfiguration();
container.inject(this);
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if (!dispatcherListeners.isEmpty()) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherInitialized(this);
}
}
} catch (Exception ex) {
if (LOG.isErrorEnabled())
LOG.error("Dispatcher initialization failed", ex);
throw new StrutsException(ex);
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 初始化default.properties，具体的初始化操作在DefaultPropertiesProvider类中</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp;&nbsp;</strong></p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; "> private void init_DefaultProperties() {
configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp;&nbsp;&nbsp;&nbsp;</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp;&nbsp;&nbsp;</strong>下面我们看下DefaultPropertiesProvider类源码：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">public void register(ContainerBuilder builder, LocatableProperties props)
throws ConfigurationException {
Settings defaultSettings = null;
try {
defaultSettings = new PropertiesSettings("org/apache/struts2/default");
} catch (Exception e) {
throw new ConfigurationException("Could not find or error in org/apache/struts2/default.properties", e);
}
loadSettings(props, defaultSettings);
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp;&nbsp; 其他的我们再次省略，大家可以浏览下各个初始化操作都加载了那些文件</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
3、doFilter方法</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; doFilter是过滤器的执行方法，它拦截提交的HttpServletRequest请求，HttpServletResponse响应，作为strtus2的核心拦截器，在doFilter里面到底做了哪些工作，我们将逐行解读其源码，源码如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
//父类向子类转：强转为http请求、响应
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
//设置编码和国际化
prepare.setEncodingAndLocale(request, response);
//创建Action上下文（重点）
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
if ( excludedPatterns != null &amp;&amp; prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request, response, true);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
execute.executeAction(request, response, mapping);
}
}
} finally {
prepare.cleanupRequest(request);
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;setEncodingAndLocale调用了dispatcher方法的prepare方法：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">/**
* Sets the request encoding and locale on the response
*/
public void setEncodingAndLocale(HttpServletRequest request, HttpServletResponse response) {
dispatcher.prepare(request, response);
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 下面我们看下prepare方法，这个方法很简单只是设置了encoding 、locale ，做的只是一些辅助的工作：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">public void prepare(HttpServletRequest request, HttpServletResponse response) {
String encoding = null;
if (defaultEncoding != null) {
encoding = defaultEncoding;
}
Locale locale = null;
if (defaultLocale != null) {
locale = LocalizedTextUtil.localeFromString(defaultLocale, request.getLocale());
}
if (encoding != null) {
try {
request.setCharacterEncoding(encoding);
} catch (Exception e) {
LOG.error("Error setting character encoding to '" + encoding + "' - ignoring.", e);
}
}
if (locale != null) {
response.setLocale(locale);
}
if (paramsWorkaroundEnabled) {
request.getParameter("foo"); // simply read any parameter (existing or not) to "prime" the request
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;<strong>Action上下文创建（重点）</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ActionContext是一个容器，这个容易主要存储request、session、application、parameters等相关信息.ActionContext是一个线程的本地变量，这意味着不同的action之间不会共享ActionContext，所以也不用考虑线程安全问题。其实质是一个Map，key是标示request、session、&#8230;&#8230;的字符串，值是其对应的对象：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">static ThreadLocal actionContext = new ThreadLocal();
Map&lt;String, Object&gt; context;
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
&nbsp;&nbsp; 下面我们看下如何创建action上下文的，代码如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">/**
*创建Action上下文，初始化thread local
*/
public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
ActionContext ctx;
Integer counter = 1;
Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
if (oldCounter != null) {
counter = oldCounter + 1;
}
//注意此处是从ThreadLocal中获取此ActionContext变量
ActionContext oldContext = ActionContext.getContext();
if (oldContext != null) {
// detected existing context, so we are probably in a forward
ctx = new ActionContext(new HashMap&lt;String, Object&gt;(oldContext.getContextMap()));
} else {
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));
//stack.getContext()返回的是一个Map&lt;String，Object&gt;，根据此Map构造一个ActionContext
ctx = new ActionContext(stack.getContext());
}
request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);
//将ActionContext存如ThreadLocal
ActionContext.setContext(ctx);
return ctx;
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 上面代码中dispatcher.createContextMap，如何封装相关参数：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">public Map&lt;String,Object&gt; createContextMap(HttpServletRequest request, HttpServletResponse response,
ActionMapping mapping, ServletContext context) {
// request map wrapping the http request objects
Map requestMap = new RequestMap(request);
// parameters map wrapping the http parameters.  ActionMapping parameters are now handled and applied separately
Map params = new HashMap(request.getParameterMap());
// session map wrapping the http session
Map session = new SessionMap(request);
// application map wrapping the ServletContext
Map application = new ApplicationMap(context);
//requestMap、params、session等Map封装成为一个上下文Map，逐个调用了map.put(Map p).
Map&lt;String,Object&gt; extraContext = createContextMap(requestMap, params, session, application, request, response, context);
if (mapping != null) {
extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
}
return extraContext;
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;我们简单看下RequestMap，其他的省略。RequestMap类实现了抽象Map，故其本身是一个Map，主要方法实现：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">//map的get实现
public Object get(Object key) {
return request.getAttribute(key.toString());
}
//map的put实现
public Object put(Object key, Object value) {
Object oldValue = get(key);
entries = null;
request.setAttribute(key.toString(), value);
return oldValue;
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 下面是源码展示了如何执行Action控制器：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException {
dispatcher.serviceAction(request, response, servletContext, mapping);
}
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
ActionMapping mapping) throws ServletException {
//封装执行的上下文环境，主要讲相关信息存储入map
Map&lt;String, Object&gt; extraContext = createContextMap(request, response, mapping, context);
// If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
boolean nullStack = stack == null;
if (nullStack) {
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
stack = ctx.getValueStack();
}
}
if (stack != null) {
extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
}
String timerKey = "Handling request from Dispatcher";
try {
UtilTimerStack.push(timerKey);
//获取命名空间
String namespace = mapping.getNamespace();
//获取action配置的name属性
String name = mapping.getName();
//获取action配置的method属性
String method = mapping.getMethod();
Configuration config = configurationManager.getConfiguration();
//根据执行上下文参数，命名空间，名称等创建用户自定义Action的代理对象
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
// if the ActionMapping says to go straight to a result, do it!
//执行execute方法，并转向结果
if (mapping.getResult() != null) {
Result result = mapping.getResult();
result.execute(proxy.getInvocation());
} else {
proxy.execute();
}
// If there was a previous value stack then set it back onto the request
if (!nullStack) {
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
}
} catch (ConfigurationException e) {
// WW-2874 Only log error if in devMode
if(devMode) {
String reqStr = request.getRequestURI();
if (request.getQueryString() != null) {
reqStr = reqStr + "?" + request.getQueryString();
}
LOG.error("Could not find action or result\n" + reqStr, e);
}
else {
LOG.warn("Could not find action or result", e);
}
sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
} catch (Exception e) {
sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
} finally {
UtilTimerStack.pop(timerKey);
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 文中对如何解析Struts.xml，如何将URL与action映射匹配为分析，有需要的我后续补全，因为StrutsXmlConfigurationProvider继承XmlConfigurationProvider，并在register方法回调父类的register，有兴趣的可以深入阅读下下XmlConfigurationProvider源码：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; "> public void register(ContainerBuilder containerBuilder, LocatableProperties props) throws ConfigurationException {
if (servletContext != null &amp;&amp; !containerBuilder.contains(ServletContext.class)) {
containerBuilder.factory(ServletContext.class, new Factory&lt;ServletContext&gt;() {
public ServletContext create(Context context) throws Exception {
return servletContext;
}
});
}
//调用父类的register，关键点所在
super.register(containerBuilder, props);
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; struts2-core-2.2.1.jar包中struts-2.1.7.dtd对于Action的定义如下：</p>
<pre name="code" class="xml" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">&lt;!ELEMENT action (param|result|interceptor-ref|exception-mapping)*&gt;
&lt;!ATTLIST action
name CDATA #REQUIRED
class CDATA #IMPLIED
method CDATA #IMPLIED
converter CDATA #IMPLIED
&gt;</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 从上述DTD中可见Action元素可以含有name 、class 、method 、converter 属性。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; XmlConfigurationProvider解析struts.xml配置的Action元素：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">   protected void addAction(Element actionElement, PackageConfig.Builder packageContext) throws ConfigurationException {
String name = actionElement.getAttribute("name");
String className = actionElement.getAttribute("class");
String methodName = actionElement.getAttribute("method");
Location location = DomHelper.getLocationObject(actionElement);
if (location == null) {
LOG.warn("location null for " + className);
}
//methodName should be null if it's not set
methodName = (methodName.trim().length() &gt; 0) ? methodName.trim() : null;
// if there isnt a class name specified for an &lt;action/&gt; then try to
// use the default-class-ref from the &lt;package/&gt;
if (StringUtils.isEmpty(className)) {
// if there is a package default-class-ref use that, otherwise use action support
/* if (StringUtils.isNotEmpty(packageContext.getDefaultClassRef())) {
className = packageContext.getDefaultClassRef();
} else {
className = ActionSupport.class.getName();
}*/
} else {
if (!verifyAction(className, name, location)) {
if (LOG.isErrorEnabled())
LOG.error("Unable to verify action [#0] with class [#1], from [#2]", name, className, location.toString());
return;
}
}
Map&lt;String, ResultConfig&gt; results;
try {
results = buildResults(actionElement, packageContext);
} catch (ConfigurationException e) {
throw new ConfigurationException("Error building results for action " + name + " in namespace " + packageContext.getNamespace(), e, actionElement);
}
List&lt;InterceptorMapping&gt; interceptorList = buildInterceptorList(actionElement, packageContext);
List&lt;ExceptionMappingConfig&gt; exceptionMappings = buildExceptionMappings(actionElement, packageContext);
ActionConfig actionConfig = new ActionConfig.Builder(packageContext.getName(), name, className)
.methodName(methodName)
.addResultConfigs(results)
.addInterceptors(interceptorList)
.addExceptionMappings(exceptionMappings)
.addParams(XmlHelper.getParams(actionElement))
.location(location)
.build();
packageContext.addActionConfig(name, actionConfig);
if (LOG.isDebugEnabled()) {
LOG.debug("Loaded " + (StringUtils.isNotEmpty(packageContext.getNamespace()) ? (packageContext.getNamespace() + "/") : "") + name + " in '" + packageContext.getName() + "' package:" + actionConfig);
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; 工作中不涉及Struts2，本周工作有个2天的空档期，稍微看了下struts2的文档，写了个demo，从源码的角度研究了下运行原理，如有分析不当请指出，我后续逐步完善更正，大家共同提高。</p>
<div><br />
</div>
</div>
<img src ="http://www.blogjava.net/niumd/aggbug/349959.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 20:58 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349959.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Nginx+tomcat配置集群负载均衡</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349958.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 12:56:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349958.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349958.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349958.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349958.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349958.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; 作者：niumd&nbsp;</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; Blog:http://ari.iteye.com</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; 转载请注明出处，谢谢</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp; 开发的应用采用F5负载均衡交换机，F5将请求转发给5台hp unix服务器，每台服务器有多个webserver实例，对外提供web服务和socket等接口服务。之初，曾有个小小的疑问为何不采用开源的apache、Nginx软件负载，F5设备动辄几十万，价格昂贵？自己一个比较幼稚的问题，后续明白：F5是操作于IOS网络模型的传输层，Nginx、apache是基于http反向代理方式，位于ISO模型的第七层应用层。直白些就是TCP UDP 和http协议的区别，Nginx不能为基于TCP协议的应用提供负载均衡。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 了解了二者之间的区别于应用场景，对Nginx产生浓厚的兴趣，阅读张宴的&lt;实战Nginx&gt;（这个85年的小伙子年轻有为羡慕+妒忌），搞明白了大致原理和配置，Ubuntu10.10，window下对Nginx+tomcat负载均衡做了配置尝试，将全部请求转发到tomcat，并未做静态，动态分开，图片防盗链等配置。<br />
<strong><span mce_style="font-size: small;" style="font-size: small; ">Nginx 介绍</span></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp;&nbsp; Nginx （发音同 engine x）是一款轻量级的Web 服务器／反向代理服务器及电子邮件（IMAP/POP3）代理服务器，并在一个BSD-like 协议下发行。&nbsp; 其特点是占有内存少，并发能力强，事实上nginx的并发能力确实在同类型的网页伺服器中表现较好.目前中国大陆使用nginx网站用户有：新浪、网易、 腾讯,另外知名的微网志Plurk也使用nginx。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp; 上面的全是Nginx介绍基本上是废话，下面转入正题，图文结合展示基本配置，首先是window环境、其次是Ubuntu环境（Vbox虚拟）。本文主要基于Nginx下配置两台tomcat，结构如下图：<br />
<img src="http://dl.iteye.com/upload/attachment/360652/25338dc2-5d45-3bc7-b9f7-102eb25c4ce9.png" mce_src="http://dl.iteye.com/upload/attachment/360652/25338dc2-5d45-3bc7-b9f7-102eb25c4ce9.png" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /><br />
<span mce_style="font-size: small;" style="font-size: small; "><strong>&nbsp;</strong></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-size: medium;" style="font-size: medium; "><strong>Window xp环境：Nginx+Tomcat6</strong></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>1、下载地址</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://nginx.org/en/download.html" mce_href="http://nginx.org/en/download.html">http://nginx.org/en/download.html</a>&nbsp;，这里我们推荐下载稳定版（stable versions），本文采用nginx-0.8.20。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
<strong>2、目录结构</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Nginx-</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |_&nbsp; conf&nbsp;&nbsp; 配置目录</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |_&nbsp; contrib</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |_&nbsp; docs 文档目录</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |_&nbsp; logs&nbsp; 日志目录</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |_&nbsp; temp 临时文件目录</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |_&nbsp; html 静态页面目录</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |_&nbsp; nginx.exe 主程序</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window下安装Nginx极其简单，解压缩到一个无空格的英文目录即可（个人习惯，担心中文出问题），双击nginx启动，这里我安装到：D:\server目录，下面涉及到的tomcat也安装在此目录。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/360565/40f0081a-c121-32e5-9157-07ee4fb800d1.jpg" mce_src="http://dl.iteye.com/upload/attachment/360565/40f0081a-c121-32e5-9157-07ee4fb800d1.jpg" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">DOS环境启动</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/360567/baf0cca2-abbf-30aa-ad04-735fa82834b8.jpg" mce_src="http://dl.iteye.com/upload/attachment/360567/baf0cca2-abbf-30aa-ad04-735fa82834b8.jpg" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">若果想停止nginx，dos环境运行命令：nginx -s stop</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
<strong>3、nginx.conf配置</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp; Nginx配置文件默认在conf目录，主要配置文件为nginx.conf，我们安装在D:\server\nginx-0.8.20、默认主配置文件为D:\server\nginx-0.8.20\nginx.conf。下面是nginx作为前端反向代理服务器的配置。</p>
<pre name="code" class="nginx.conf" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">#Nginx所用用户和组，window下不指定
#user  niumd niumd;
#工作的子进程数量（通常等于CPU数量或者2倍于CPU）
worker_processes  2;
#错误日志存放路径
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
error_log  logs/error.log  info;
#指定pid存放文件
pid        logs/nginx.pid;
events {
#使用网络IO模型linux建议epoll，FreeBSD建议采用kqueue，window下不指定。
#use epoll;
#允许最大连接数
worker_connections  2048;
}
http {
include       mime.types;
default_type  application/octet-stream;
#定义日志格式
#log_format  main  '$remote_addr - $remote_user [$time_local] $request '
#                  '"$status" $body_bytes_sent "$http_referer" '
#                  '"$http_user_agent" "$http_x_forwarded_for"';
#access_log  off;
access_log  logs/access.log;
client_header_timeout  3m;
client_body_timeout    3m;
send_timeout           3m;
client_header_buffer_size    1k;
large_client_header_buffers  4 4k;
sendfile        on;
tcp_nopush      on;
tcp_nodelay     on;
#keepalive_timeout  75 20;
include    gzip.conf;
upstream localhost {
#根据ip计算将请求分配各那个后端tomcat，许多人误认为可以解决session问题，其实并不能。
#同一机器在多网情况下，路由切换，ip可能不同
#ip_hash;
server localhost:18081;
server localhost:18080;
}
server {
listen       80;
server_name  localhost;
location / {
proxy_connect_timeout   3;
proxy_send_timeout      30;
proxy_read_timeout      30;
proxy_pass http://localhost;
}
}
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
&nbsp;&nbsp; 代理设置如下：</p>
<pre name="code" class="proxy.conf" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">proxy_redirect          off;
proxy_set_header        Host $host;
proxy_set_header        X-Real-IP $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size    10m;
client_body_buffer_size 128k;
proxy_connect_timeout   300;
proxy_send_timeout      300;
proxy_read_timeout      300;
proxy_buffer_size       4k;
proxy_buffers           4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; gzip压缩相关配置如下：</p>
<pre name="code" class="gzip.conf" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">gzip              on;
gzip_min_length      1000;
gzip_types         text/plain text/css application/x-javascript;
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
<strong>&nbsp; 4、Tomcat配置</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp; 对于tomcat大家都很熟悉，只需要修改server.xml配置文件即可，这里我们以apache-tomcat-6.0.14为例，分别在server目录，解压缩并命名为：apache-tomcat-6.0.14_1、apache-tomcat-6.0.14_2。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp; 第一处端口修改：</p>
<pre name="code" class="xml" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">&lt;!--  修改port端口：18006 俩个tomcat不能重复，端口随意，别太小--&gt;
&lt;Server port="18006" shutdown="SHUTDOWN"&gt;
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
&nbsp;&nbsp; 第二处端口修改：</p>
<pre name="code" class="xml" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">&lt;!-- port="18081" tomcat监听端口，随意设置，别太小 --&gt;
&lt;Connector port="18081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" /&gt;
&nbsp;</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 第三处端口修改：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">&lt;Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /&gt;
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; Engine元素增加jvmRoute属性：</p>
<pre name="code" class="xml" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">&lt;Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1"&gt;
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
&nbsp;&nbsp;&nbsp; 两个tomcat的端口别重复，保证能启动起来，另一个tomcat配置希捷省略，监听端口为18080，附件中我们将上传所有的配置信息。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
<strong>5、验证配置与测试负载均衡</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp; 首先测试nginx配置是否正确，测试命令：nginx -t&nbsp; (默认验证:conf\nginx.conf),也可以指定配置文件路径。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;此例nginx安装目录：D:\server\nginx-0.8.20，dos环境下图画面成功示例：<br />
<img src="http://dl.iteye.com/upload/attachment/360606/488826c2-d5a6-3a5a-8b6b-ea55c33ab01b.jpg" mce_src="http://dl.iteye.com/upload/attachment/360606/488826c2-d5a6-3a5a-8b6b-ea55c33ab01b.jpg" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;其次验证tomcat，启动两个tomcat，不出现端口冲突即为成功（tomcat依赖的java等搞&#8220;挨踢&#8221;的就废话不说了）；</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/360608/53ac9d08-9c6e-3ea4-a7fa-8c0bb1f3e2fd.jpg" mce_src="http://dl.iteye.com/upload/attachment/360608/53ac9d08-9c6e-3ea4-a7fa-8c0bb1f3e2fd.jpg" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 最后验证配置负载均衡设置，<a href="http://localhost/" mce_href="http://localhost/">http://localhost/</a>&nbsp;或<a href="http://localhost/index.jsp" mce_href="http://localhost/index.jsp">http://localhost/index.jsp</a>&nbsp;。我修改了index.jsp页面，增加日志输出信息，便于观察。注意：左上角小猫头上的：access tomcat2、access tomcat1。说明访问了不同的tomcat。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/360614/ae669075-5a52-3116-b2a1-c455e0c7d2f3.jpg" mce_src="http://dl.iteye.com/upload/attachment/360614/ae669075-5a52-3116-b2a1-c455e0c7d2f3.jpg" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /><br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; 至此window下nginx+tomcat负载均衡配置结束，关于tomcat Session的问题通常是采用memcached，或者采用nginx_upstream_jvm_route ，他是一个 Nginx 的扩展模块，用来实现基于 Cookie 的 Session Sticky 的功能。如果tomcat过多不建议session同步，server间相互同步session很耗资源，高并发环境容易引起Session风暴。请根据自己应用情况合理采纳session解决方案。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;作者：niumd&nbsp;</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; Blog:http://ari.iteye.com</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-size: medium;" style="font-size: medium; "><strong>Ubuntu10.10环境：Nginx+Tomcat6</strong></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
我们下面简单说下ubuntu10.10下如何安装配置，主要以图片为主，简单解释。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong><span mce_style="color: #000000;" style="color: #000000; ">1、下载Nginx</span></strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 地址：<a href="http://nginx.org/en/download.html" mce_href="http://nginx.org/en/download.html">http://nginx.org/en/download.html</a>&nbsp;，linux版本：nginx-0.8.20.tar.。解压缩命令：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
tar -zxvf nginx-0.8.20.tar.gz</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
<strong>2、编译安装Nginx</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp;&nbsp; Nginx依赖一些其他PCRE、openssl（依赖libssl-dev），本人笔记本Ubuntu环境已经安装PCRE，仅需安装依赖的openssl，下面我们简单说下如何安装PCRE和openssl等</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
&nbsp;&nbsp;&nbsp;&nbsp; PCRE下载地址：<a href="ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/" mce_href="ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/">ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/</a></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="shell" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">tar zxvf  pcre-8.01.tar.gz
cd pcre-8.01
sudo ./configure
sodu make
sodu make install
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;openssl通过apt-get install安装，命令、截图如下：</p>
<pre name="code" class="shell" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">sudo apt-get install openssl
sudo apt-get install libssl-dev
//如缺少其他包，请采用此方法安装，ubuntu有依赖提示
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/360643/8a26cf32-8136-3583-956a-4d86f233f644.png" mce_src="http://dl.iteye.com/upload/attachment/360643/8a26cf32-8136-3583-956a-4d86f233f644.png" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /><br />
&nbsp;<br />
&nbsp;依赖的软件包安装完毕，下面来编译Nginx：</p>
<pre name="code" class="shell" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">#将window共享目录软件拷贝到当前工作目录
cp /mnt/fileshare/nginx-0.8.20.tar.gz ./
#解压缩软件包
tar zxvf nginx-0.8.20.tar.gz
cd nginx-0.8.20
//编译源码,默认使用nobody，指定本机已存在的用户，组，启用nginx-status功能，监控nginx状态。启动debug
sudo ./configure  --user=niumd --group=niumd --with-debug --with-http_stub_status_module
sudo make
sudo make install
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
&nbsp;&nbsp; 截图 如下：<br />
<img src="http://dl.iteye.com/upload/attachment/360645/95a8c78c-9bab-36f8-aaf8-fa2c77917d44.png" mce_src="http://dl.iteye.com/upload/attachment/360645/95a8c78c-9bab-36f8-aaf8-fa2c77917d44.png" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">安装结果截图如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/360647/9a4db10e-d6d0-3131-b652-3040a9a575ae.png" mce_src="http://dl.iteye.com/upload/attachment/360647/9a4db10e-d6d0-3131-b652-3040a9a575ae.png" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">编译安装正确结束，按照上述window下方法检查默认配置，然后在默认配置下启动nginx，访问<a href="http://127.0.0.1/" mce_href="http://127.0.0.1">http://127.0.0.1</a>&nbsp;，如下图说明成功</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/360649/83cb2060-085a-3cc6-9fe7-3703b46ab745.png" mce_src="http://dl.iteye.com/upload/attachment/360649/83cb2060-085a-3cc6-9fe7-3703b46ab745.png" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">Nginx配置成功后我们对window下nginx.conf少做修改，如下：</p>
<pre name="code" class="ubuntu Nginx.conf" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">#Nginx所用用户和组
user  niumd niumd;
#工作的子进程数量（通常等于CPU数量或者2倍于CPU）
worker_processes  2;
#错误日志存放路径
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
error_log  logs/error.log  info;
#指定pid存放文件
pid        logs/nginx.pid;
events {
#使用网络IO模型linux建议epoll，FreeBSD建议采用kqueue
use epoll;
#允许最大连接数
worker_connections  2048;
}
http {
include       mime.types;
default_type  application/octet-stream;
#定义日志格式
#log_format  main  '$remote_addr - $remote_user [$time_local] $request '
#                  '"$status" $body_bytes_sent "$http_referer" '
#                  '"$http_user_agent" "$http_x_forwarded_for"';
#access_log  off;
access_log  logs/access.log;
client_header_timeout  3m;
client_body_timeout    3m;
send_timeout           3m;
client_header_buffer_size    1k;
large_client_header_buffers  4 4k;
sendfile        on;
tcp_nopush      on;
tcp_nodelay     on;
#keepalive_timeout  75 20;
include    gzip.conf;
upstream localhost {
#ip_hash
#ip_hash;
server localhost:18081;
server localhost:18080;
}
server {
listen       80;
server_name  localhost;
location / {
proxy_connect_timeout   3;
proxy_send_timeout      30;
proxy_read_timeout      30;
proxy_pass http://localhost;
}
}
}
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;对于上面关于ubuntu下Nginx配置和window下基本相同，区别在使用的IO网络模型，linux下建议使用epoll，另外就是运行所用的用户和组；</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>3、配置tomcat</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 请参考window下配置，完全相同。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="color: #000000;" style="color: #000000; "><strong>4、启动停止nginx</strong></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp;&nbsp;&nbsp;&nbsp;</strong>ubuntu下启动nginx与window稍有不同，大致启动停止方法如下。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">#nginx目录执行
sbin/nginx
或通过-c 指定配置文件
sbin/nginx -c usr/local/nginx8.20/conf/nginx/conf</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="shell" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">niumd@niumd-laptop:/usr/local/nginx$ pwd
/usr/local/nginx
niumd@niumd-laptop:/usr/local/nginx$ sudo sbin/nginx -t
the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
configuration file /usr/local/nginx/conf/nginx.conf test is successful
niumd@niumd-laptop:/usr/local/nginx$ sudo sbin/nginx -v
nginx version: nginx/0.8.20
niumd@niumd-laptop:/usr/local/nginx$ sudo sbin/nginx -V
nginx version: nginx/0.8.20
built by gcc 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
configure arguments: --user=niumd --group=niumd --with-debug --with-http_sub_module
niumd@niumd-laptop:/usr/local/nginx$ sudo sbin/nginx
niumd@niumd-laptop:/usr/local/nginx$ ps -ef|grep nginx
root      5158     1  0 22:32 ?        00:00:00 nginx: master process sbin/nginx
niumd     5159  5158  0 22:32 ?        00:00:00 nginx: worker process
niumd     5161  1577  0 22:32 pts/0    00:00:00 grep --color=auto nginx
niumd@niumd-laptop:/usr/local/nginx$ </pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; &nbsp;&nbsp; 我们通过ps&nbsp; -ef|grep nginx,看到如下结果:</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/360672/64e32e0c-10a4-3cb6-a1d4-87045140b37a.png" mce_src="http://dl.iteye.com/upload/attachment/360672/64e32e0c-10a4-3cb6-a1d4-87045140b37a.png" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">注意：在启动时linux提示一句警告【warn】&#8230;&#8230;，是因为我们设置的 #允许最大连接数 worker_connections&nbsp; 2048，超过linux默认1024的限制。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 停止：kill -信号类型 pid</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nginx/logs目录下有个nginx。pid的文件，此文件记录了每次运行的pid，也可以通过ps命令查询。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">信号类型如下：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<table mce_style="height: 40px;" border="0" width="400" class="mceItemTable" height="40" style="height: 40px; ">
    <caption style="border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: #bbbbbb; border-right-color: #bbbbbb; border-bottom-color: #bbbbbb; border-left-color: #bbbbbb; "><strong>信号控制</strong></caption>
    <tbody>
        <tr>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><strong>信号类型</strong></td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; "><strong>描述</strong></td>
        </tr>
        <tr>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">RERM.INT</td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">快速关闭</td>
        </tr>
        <tr>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">HUP</td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">平滑重启，加载配置</td>
        </tr>
        <tr>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">USR1</td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">重新加载日志</td>
        </tr>
        <tr>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">USER2</td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">平滑升级执行程序</td>
        </tr>
        <tr>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">WINCH</td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">从容关闭工作进程</td>
        </tr>
        <tr>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">QUIT</td>
            <td style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; ">从容关闭</td>
        </tr>
    </tbody>
</table>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">参考资料：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><a href="http://www.oschina.net/bbs/thread/9301" mce_href="http://www.oschina.net/bbs/thread/9301">http://www.oschina.net/bbs/thread/9301</a></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">oschina.net 生产配置，此网站采用java语言，nginx，tomcat服务器。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><a href="http://nginx.org/" mce_href="http://nginx.org/">http://nginx.org/</a></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">张宴：&lt;&lt;实战Nginx&gt;&gt;</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
</div>
<img src ="http://www.blogjava.net/niumd/aggbug/349958.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 20:56 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349958.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ubuntu11 Unity 2D桌面</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349955.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 12:54:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349955.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349955.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349955.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349955.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349955.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">
<h5 mce_style="text-align: center;" style="font-size: 0.83em; text-align: center; "><span mce_style="font-size: 18px;" style="font-size: 18px; ">Ubuntu11.04如何设置2D Unity桌面</span></h5>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; &nbsp; Ubuntu11.04一发布就迫不及待的尝鲜，虚拟机环境不支持Unity 3D,尝试了下Unity 2D，效果很炫。安装很简单，给大家分享下。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="white-space: pre;" style="white-space: pre; ">	</span><span mce_style="font-family: Arial, serif; font-size: 14px; line-height: 22px;" style="font-family: Arial, serif; font-size: 14px; line-height: 22px; ">Terminal 键入如下命令：</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">sudo add-apt-repository ppa:unity-2d-team/unity-2d-daily
sudo apt-get update
sudo apt-get install unity-2d</pre>
&nbsp;
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; &nbsp;这三行命令就不解释，Ubuntu新手老手都应该清楚，经过10-20分钟的等待（取决你的网速和选择更新源），Ubuntu安装Unity-2d和依赖包，安装完毕，log out，这点比windows强，xp都是提示重启的。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;上图：登陆界面选择Unity 2D。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><img src="http://dl.iteye.com/upload/attachment/475018/0cb6e7d0-37f4-3a6a-b393-c060f316d86a.jpg" mce_src="http://dl.iteye.com/upload/attachment/475018/0cb6e7d0-37f4-3a6a-b393-c060f316d86a.jpg" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="font-family: Arial, serif;" style="font-family: Arial, serif; "><span mce_style="font-size: 14px; line-height: 22px;" style="font-size: 14px; line-height: 22px; ">&nbsp;上图秀桌面：</span></span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
<img src="http://dl.iteye.com/upload/attachment/475016/8b87cf08-2d68-38a9-ae33-174151f3e743.png" mce_src="http://dl.iteye.com/upload/attachment/475016/8b87cf08-2d68-38a9-ae33-174151f3e743.png" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
</div>
<img src ="http://www.blogjava.net/niumd/aggbug/349955.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 20:54 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349955.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>crontab命令用法</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349957.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 12:54:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349957.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349957.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349957.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349957.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349957.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp; &nbsp;Linux提供了用户控制例行任务的命令crontab，常用于每间隔一定时间循环执行一些脚本，此处我们暂时称为：Linux定时任务。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="shell" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">#问下男人crontab的用法
man crontab
crontab [ -u user ] { -l | -r [ -i ] | -e }
参数：
-u：只有root才可以执行此任务
-l ：查看crontab工作内容
-e：编辑crontab工作内容
-r ：删除crontab工作内容
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><strong>&nbsp;&nbsp;&nbsp;crontab应用场景举例：定时采集远程服务器文件</strong></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 手机发送短信，短信回以文本形式记录在交换机上形成短信话单，短信话单通常是达到5M，如果不满5m则每五分钟形成一个话单（不同的交换机可能存在差异）。如果对话单计费，当然需要对短信话单进行采集，然后进行后续计费工作。我们假设采用shell或者python脚本采集，暂且用shell举例，假设采集shell为acquisition.sh ，每间隔1分钟采集一次。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 命令终端执行：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">#标示编辑例行任务
crontab -e</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 然后我们将会看到如下画面：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;<br />
<img src="http://dl.iteye.com/upload/attachment/384214/873a6227-c863-39cd-af72-ebfbdee15b96.png" mce_src="http://dl.iteye.com/upload/attachment/384214/873a6227-c863-39cd-af72-ebfbdee15b96.png" alt="" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /><br />
&nbsp;</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp; 已经进入VI 编辑模式，在里面输入下面这行，按下ESC-&gt;：-&gt;wq就保存了</p>
<pre name="code" class="python" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">#每间隔一分钟执行一次采集脚本
*/1 * * * * crontab  /路径/acquisition.sh
</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; crontab的格式为：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 分钟&nbsp; 小时 日&nbsp; 月 周 crontab&nbsp;&nbsp; 待执行命令或者脚本&nbsp;</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp; 其中：* 代表任何时间都接受，如上例小时、日期、月份、周都为*</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;，代表分割时间段，如分钟修改为：0,1,2,3,4,5 即任何小时地1,2，&#8230;&#8230;6分钟都执行</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - 代表时间段上面的每间隔一分钟可以标示为0-59；</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /n&nbsp;代表每间隔，分钟位置：*/5标示每间隔五分钟</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;注意：*和*之间只有一个空格；</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">EOF</p>
</div>
<img src ="http://www.blogjava.net/niumd/aggbug/349957.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 20:54 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349957.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅谈Selector创建机制</title><link>http://www.blogjava.net/niumd/archive/2011/05/10/349954.html</link><dc:creator>空白</dc:creator><author>空白</author><pubDate>Tue, 10 May 2011 12:53:00 GMT</pubDate><guid>http://www.blogjava.net/niumd/archive/2011/05/10/349954.html</guid><wfw:comment>http://www.blogjava.net/niumd/comments/349954.html</wfw:comment><comments>http://www.blogjava.net/niumd/archive/2011/05/10/349954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/niumd/comments/commentRss/349954.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/niumd/services/trackbacks/349954.html</trackback:ping><description><![CDATA[<div style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 8px; margin-right: 8px; margin-bottom: 8px; margin-left: 8px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; background-position: initial initial; background-repeat: initial initial; ">
<p mce_style="text-align: left;" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-align: left; "><span mce_style="white-space: pre;" style="white-space: pre; ">	前段时间阅读mina源码时，理</span>解<span mce_style="font-family: monospace; white-space: pre;" style="font-family: monospace; white-space: pre; ">Selector实例化机制细节有点疑惑疑惑，主要是</span><span mce_style="font-family: monospace; white-space: pre;" style="font-family: monospace; white-space: pre; ">SelectorProvider的细节实现方面。</span></p>
<p mce_style="text-align: left;" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; text-align: left; "><span mce_style="font-family: monospace; white-space: pre;" style="font-family: monospace; white-space: pre; ">通常创建一个Selector，通过静态open方法创建一个实例。</span>代码如下：</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">Selector selector = Selector.open();</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">观察JDK源码发现Select的创建通过<span mce_style="white-space: pre;" style="white-space: pre; ">SelectorProvider辅助类来完成</span>：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">进一步观察<span mce_style="white-space: pre;" style="white-space: pre; ">SelectorProvider类provider方法源码，引用到类sun.nio.ch.DefaultSelectorProvider，开始的时候由于在JDK API</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="white-space: pre;" style="white-space: pre; ">中没找到该类，源码里面也没找到，比较疑惑如何创建的。</span><span mce_style="white-space: pre;" style="white-space: pre; ">今天在rt.jar找到了该类，</span>并找到其对源码。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">/**
* Returns the default SelectorProvider.
*/
public static SelectorProvider create() {
PrivilegedAction pa = new GetPropertyAction("os.name");
String osname = (String) AccessController.doPrivileged(pa);
if ("SunOS".equals(osname)) {//1、如果SunOS
return new sun.nio.ch.DevPollSelectorProvider();
}
//2、Linux 内核&gt;=2.6
// use EPollSelectorProvider for Linux kernels &gt;= 2.6
if ("Linux".equals(osname)) {
pa = new GetPropertyAction("os.version");
String osversion = (String) AccessController
.doPrivileged(pa);
String[] vers = osversion.split("\\.", 0);
if (vers.length &gt;= 2) {
try {
int major = Integer.parseInt(vers[0]);
int minor = Integer.parseInt(vers[1]);
if (major &gt; 2 || (major == 2 &amp;&amp; minor &gt;= 6)) {
return new sun.nio.ch.EPollSelectorProvider();
}
} catch (NumberFormatException x) {
// format not recognized
}
}
}
return new sun.nio.ch.PollSelectorProvider();
}</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">其<span mce_style="white-space: pre;" style="white-space: pre; ">create方法根据不同的操作系统构建不同的</span><span mce_style="white-space: pre;" style="white-space: pre; ">SelectorProvider，主要分为unix、linux，other，linux针对内核2.6以上</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="white-space: pre;" style="white-space: pre; ">通过epoll。</span><span mce_style="white-space: pre;" style="white-space: pre; ">获取系统环境中的os.name、os.version观察下不同平台的细节。</span></p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<pre name="code" class="java" style="color: #000000; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; background-position: initial initial; background-repeat: initial initial; ">System.out.println(System.getProperty("os.name"));
System.out.println(System.getProperty("os.version"));
System.out.println(java.nio.channels.spi.SelectorProvider.provider());</pre>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;通过在不同的操作系统上执行如下代码即可区分：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">win XP sp3：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<div class="quote_title" style="font-weight: bold; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; margin-top: 5px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; ">&nbsp;写道</div>
<div class="quote_div" style="border-left-color: #cccccc; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; ">Windows XP<br />
5.1<br />
sun.nio.ch.WindowsSelectorProvider@1fb8ee3</div>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">&nbsp;ubuntu 11.04：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<div class="quote_title" style="font-weight: bold; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; margin-top: 5px; margin-right: 0px; margin-bottom: 0px; margin-left: 15px; ">&nbsp;写道</div>
<div class="quote_div" style="border-left-color: #cccccc; margin-top: 0px; margin-right: 5px; margin-bottom: 5px; margin-left: 15px; padding-top: 3px; padding-right: 3px; padding-bottom: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #fafafa; ">Linux<br />
2.6.38-8-generic<br />
sun.nio.ch.EPollSelectorProvider@160c21a</div>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">JDK对linux内核2.6以上版本默认采用epoll，Linux下性能得到一定幅度提升。</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><br />
</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; ">参考：</p>
<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><span mce_style="white-space: pre;" style="white-space: pre; ">DefaultSelectorProvider源码：</span><a href="http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Platform/solaris/sun/nio/ch/DefaultSelectorProvider.java.htm" mce_href="http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Platform/solaris/sun/nio/ch/DefaultSelectorProvider.java.htm">http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Platform/solaris/sun/nio/ch/DefaultSelectorProvider.java.htm</a></p>
</div>
<img src ="http://www.blogjava.net/niumd/aggbug/349954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/niumd/" target="_blank">空白</a> 2011-05-10 20:53 <a href="http://www.blogjava.net/niumd/archive/2011/05/10/349954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>