﻿<?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-石建 | Fat Mind-随笔分类-一点理解</title><link>http://www.blogjava.net/shijian/category/46547.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 06 Jul 2013 07:59:23 GMT</lastBuildDate><pubDate>Sat, 06 Jul 2013 07:59:23 GMT</pubDate><ttl>60</ttl><item><title>meta学习 - 前辈kafka</title><link>http://www.blogjava.net/shijian/archive/2013/07/06/378641.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Sat, 06 Jul 2013 06:57:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2013/07/06/378641.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/378641.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2013/07/06/378641.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/378641.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/378641.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><br /></p><a href="http://incubator.apache.org/kafka/design.html">http://incubator.apache.org/kafka/design.html</a><span style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; ">
</span><div>
<br />
1.<span class="Apple-style-span" style="font-size: 21px; font-weight: bold; ">Why we built this</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; "><br />
</span>&nbsp;&nbsp; &nbsp;asd（activity stream data）数据是任何网站的一部分，反映网站使用情况，如：那些内容被搜索、展示。通常，此部分数据被以log方式记录在文件，然后定期的整合和分析。od（operation data）是关于机器性能数据，和其它不同途径整合的操作数据。<br />
&nbsp;&nbsp; &nbsp;在近几年，asd和od变成一个网站重要的一部分，更复杂的基础设施是必须的。<br />
<span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; ">&nbsp;&nbsp; &nbsp; 数据特点：<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;a、大吞吐量的不变的ad，对实时计算是一个挑战，会很容易超过10倍or100倍。</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; ">&nbsp;<br />
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;b、传统的记录log方式是<span class="Apple-style-span" style="font-family: verdana, 'courier new'; font-size: 14px; line-height: 21px; color: #000000; ">respectable and scalable方式去支持离线处理，但是延迟太高。<br />
</span></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; "><span class="Apple-style-span" style="font-size: 15px;">&nbsp;&nbsp;&nbsp;&nbsp;Kafka is intended to be a single queuing platform that can support both offline and online use cases.</span><br />
<br />
<span class="Apple-style-span" style="font-size: 15px;">2.</span><span class="Apple-style-span" style="font-size: 30px; font-weight: bold; ">Major Design Elements</span><br />
<div>
<p style="font-size: 15px; ">There is a small number of major design decisions that make Kafka different from most other messaging systems:</p>
<ol style="font-size: 15px; ">
     <li>Kafka is designed for persistent messages as the common case；<span class="Apple-style-span" style="font-size: 14px; ">消息持久</span></li>
     <li>Throughput rather than features are the primary design constraint；<span class="Apple-style-span" style="font-size: 14px; ">吞吐量是第一要求</span></li>
     <li>State about&nbsp;<em>what</em>&nbsp;has been consumed is maintained as part of the consumer not the server；<span class="Apple-style-span" style="font-size: 14px; ">状态由客户端维护</span></li>
     <li>Kafka is explicitly distributed. It is assumed that producers, brokers, and consumers are all spread over multiple machines；<span class="Apple-style-span" style="font-size: 14px; ">必须是分布式<br />
     </span></li>
</ol>
</div>
3.<span class="Apple-style-span" style="font-size: 21px; font-weight: bold; ">Basics</span><br />
<span style="font-size: 15px; "><em>&nbsp;&nbsp;&nbsp;&nbsp;Messages</em></span>&nbsp;<span style="font-size: 15px; ">are the fundamental unit of communication</span>；<br />
&nbsp;&nbsp;&nbsp;&nbsp;Messages are</span>&nbsp;<span style="font-size: 15px; "><em>published</em></span>&nbsp;<span style="font-size: 15px; ">to a</span>&nbsp;<span style="font-size: 15px; "><em>topic</em></span>&nbsp;<span style="font-size: 15px; ">by a</span>&nbsp;<span style="font-size: 15px; "><em>producer&nbsp;</em></span><span style="font-size: 15px; ">which means they are physically sent to a server acting as a</span>&nbsp;<span style="font-size: 15px; "><em>broker，消息被生产者发布到一个topic，意味着物理的发送消息到broker；<br />
</em></span>&nbsp;&nbsp; &nbsp;多个consumer订阅一个topic，则此topic的每个消息都会被分发到每个consumer；<br />
&nbsp;&nbsp; &nbsp;kafka是分布式：producer、broker、consumer，均可以由集群的多台机器组成，相互协作 a logic group；<br />
&nbsp;&nbsp; &nbsp;属于同一个consumer group的每一个consumer process，每个消息能准确的由其中的一个process消费；<span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; ">A more common case in our own usage is that we have multiple logical consumer groups, each consisting of a cluster of consuming machines that act as a logical whole.<br />
</span>&nbsp;&nbsp; &nbsp;kafka不管一个topic有多少个consumer，其消息仅会存储一份。<br />
<br />
4.<span class="Apple-style-span" style="font-size: 21px;"><strong>Message Persistence and Caching</strong></span><br />
<span class="Apple-style-span" style="font-size: 16px; font-weight: bold; "><br />
4.1 Don't fear the filesystem !<br />
</span>&nbsp;&nbsp; &nbsp;kafka完全依赖文件系统去存储和cache消息；<br />
&nbsp;&nbsp; &nbsp;大家通常对磁盘的直觉是'很慢'，则使人们对持久化结构，是否能提供有竞争力的性能表示怀疑；实际上，磁盘到底有多慢或多块，完全取决于如何使用磁盘，<span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; ">a properly designed disk structure can often be as fast as the network.</span><br />
&nbsp;&nbsp; &nbsp;<a href="http://baike.baidu.com/view/969385.htm">http://baike.baidu.com/view/969385.htm</a>&nbsp;raid-5&nbsp;<br />
&nbsp;&nbsp; &nbsp;<a href="http://www.china001.com/show_hdr.php?xname=PPDDMV0&amp;dname=66IP341&amp;xpos=172">http://www.china001.com/show_hdr.php?xname=PPDDMV0&amp;dname=66IP341&amp;xpos=172</a>&nbsp;磁盘种类<br />
&nbsp;&nbsp; &nbsp;磁盘顺序读写的性能非常高，&nbsp;<span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; "><span class="Apple-style-span" style="font-size: 15px;">linear writes on a 6 7200rpm SATA RAID-5 array is about 300MB/sec；</span><span class="Apple-style-span" style="font-family: verdana, 'courier new'; font-size: 14px; line-height: 21px; color: #000000; ">These linear reads and writes are the most predictable of all usage patterns, and hence the one detected and optimized best by the operating system using read-ahead and write-behind techniques。顺序读写是最可预见的模式，因此操作系统通过read-head和write-behind技术去优化。<br />
</span><span class="Apple-style-span" style="font-size: 15px;">&nbsp;&nbsp; &nbsp;现代操作系统，用mem作为disk的cache；Any modern OS will happily divert&nbsp;</span><em style="font-size: 15px; ">all</em><span class="Apple-style-span" style="font-size: 15px;">&nbsp;free memory to disk caching with little performance penalty when the memory is reclaimed. All disk reads and writes will go through this unified cache.&nbsp;</span><br />
<span class="Apple-style-span" style="font-size: 15px;">&nbsp;&nbsp; &nbsp;Jvm：a、对象的内存开销是非常大的，通常是数据存储的2倍；b、当heap数据增大时，gc代价越来越大；</span><br />
<span class="Apple-style-span" style="font-size: 15px;">&nbsp;&nbsp;&nbsp;&nbsp;As a result of these factors using the filesystem and relying on pagecache is superior to maintaining an in-memory cache or other structure。依赖文件系统和pagecache是优于mem cahce或其它结构的。</span><br />
<span class="Apple-style-span" style="font-size: 15px;">&nbsp;&nbsp; &nbsp;数据压缩，Doing so will result in a cache of up to 28-30GB on a 32GB machine without GC penalties.&nbsp;</span><br />
<span class="Apple-style-span" style="font-size: 15px;">&nbsp;&nbsp; &nbsp;This suggests a design which is very simple: maintain as much as possible in-memory and flush to the filesystem only when necessary. 尽可能的维持在内存中，仅当必须时写回到文件系统.</span><br />
<span class="Apple-style-span" style="font-size: 15px;">&nbsp;&nbsp; &nbsp;当数据被立即写回到持久化的文件，而未调用flush，其意味着数据仅被写入到os pagecahe，在后续某个时间由os flush。Then we add a configuration driven flush policy to allow the user of the system to control how often data is flushed to the physical disk (every N messages or every M seconds) to put a bound on the amount of data "at risk" in the event of a hard crash. 提供flush策略。</span><br />
<span class="Apple-style-span" style="font-size: 15px;"><br />
4.2&nbsp;</span><span class="Apple-style-span" style="font-size: 18px; font-weight: bold; ">Constant Time Suffices<br />
</span>&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">The persistent data structure used in messaging systems metadata is often a BTree. BTrees are the most versatile data structure available, and make it possible to support a wide variety of transactional and non-transactional semantics in the messaging system.</span><span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; "><br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;Disk seeks come at 10 ms a pop, and each disk can do only one seek at a time so parallelism is limited. Hence even a handful of disk seeks leads to very high overhead.&nbsp;<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;Furthermore BTrees require a very sophisticated page or row locking implementation to avoid locking the entire tree on each operation.
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">The implementation must pay a fairly high price for row-locking or else effectively serialize all reads.</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp; 持久化消息的元数据通常是BTree结构，但磁盘结构，其代价太大。原因：寻道、避免锁整棵树。<br />
&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: yellow; ">Intuitively a persistent queue could be built on simple reads and appends to files as is commonly the case with logging solutions.</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp; 持久化队列可以构建在读和append to 文件。所以不支持BTree的一些语义，但其好处是：O(1)消耗，无锁读写。<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="background-color: #ffffff; "><font class="Apple-style-span" color="#222222" face="Arial, sans-serif"><span class="Apple-style-span" style="font-size: 15px; line-height: 22px;">the performance is completely decoupled from the data size--one server can now take full advantage of a number of cheap, low-rotational speed 1+TB SATA drives.&nbsp;
<div style="display: inline-block; "></div>
</span></font></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">Though they have poor seek performance, these drives often have comparable performance for large reads and writes at 1/3 the price and 3x the capacity.</span><span class="Apple-style-span" style="background-color: #ffffff; "><font class="Apple-style-span" color="#222222" face="Arial, sans-serif"><span class="Apple-style-span" style="font-size: 15px; line-height: 22px;"><br />
</span></font></span><span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; "><br />
4.3&nbsp;<span class="Apple-style-span" style="color: #2e4a8e; font-size: 23px; font-weight: bold; background-color: #ffffff; ">Maximizing Efficiency</span><br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;Furthermore we assume each message published is read at least once (and often multiple times), hence we optimize for consumption rather than production. 更进一步，我们假设被发布的消息至少会读一次，因此优化consumer优先于producer。<br />
</span><span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; ">&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">There are two common causes of inefficiency : <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;two many network requests, （
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;APIs are built around a "message set" abstraction，
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">This allows network requests to group messages together and amortize the overhead of the network roundtrip rather than sending a single message at a time.</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">） 仅提供批量操作api，则每次网络开销是平分在一组消息，而不是单个消息。<br />
&nbsp; &nbsp; and excessive byte copying.（
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">The message log maintained by the broker is itself just a directory of message sets that have been written to disk.
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">Maintaining this common format allows optimization of the most important operation : network transfer of persistent log chunks.</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">）<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;To understand the impact of sendfile, it is important to understand the common data path for transfer of data from file to socket:
<ol>
     <li>The operating system reads data from the disk into pagecache in kernel space</li>
     <li>The application reads the data from kernel space into a user-space buffer</li>
     <li>The application writes the data back into kernel space into a socket buffer</li>
     <li>The operating system copies the data from the socket buffer to the NIC buffer where it is sent over the network<br />
     </li>
</ol>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp; 利用os提供的zero-copy，
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">only the final copy to the NIC buffer is needed.</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "> <br />
<br />
4.4&nbsp;<span class="Apple-style-span" style="color: #2e4a8e; font-size: 23px; font-weight: bold; ">End-to-end Batch Compression</span><br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;In many cases the bottleneck is actually not CPU but network. This is particularly true for a data pipeline that needs to send messages across data centers.
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">Efficient compression requires compressing multiple messages together rather than compressing each message individually.&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">Ideally this would be possible in an end-to-end fashion &#8212; that is, data would be compressed prior to sending by the producer and remain compressed on the server, only being decompressed by the eventual consumers.</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;<br />
&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">A batch of messages can be clumped together compressed and sent to the server in this form. This batch of messages will be delivered all to the same consumer and will remain in compressed form until it arrives there.<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp; 理解：kafka&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">producer&nbsp;</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">api 提供批量压缩，broker不对此批消息做任何操作，且以压缩的方式，一起被发送到consumer。<br />
<br />
4.5&nbsp;<span class="Apple-style-span" style="color: #2e4a8e; font-size: 23px; font-weight: bold; ">Consumer state</span><br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;Keeping track of&nbsp;<em>what</em>&nbsp;has been consumed is one of the key things a messaging system must provide.&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">State tracking requires updating a persistent entity and potentially causes random accesses.&nbsp;<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">Most messaging systems keep metadata about what messages have been consumed on the broker. That is, as a message is handed out to a consumer, the broker records that fact locally.&nbsp;大部分消息系统，存储是否被消费的元信息在broker。则是说，一个消息被分发到一个consumer，broker记录。<br />
&nbsp; &nbsp; 问题：当consumer消费失败后，会导致消息丢失；改进：每次consumer消费后，给broker ack，若broker在超时时间未收到ack，则重发此消息。<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp; 问题：1.当消费成功，但未ack时，会导致消费2次 &nbsp;2.
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;now the broker must keep multiple states about every single message &nbsp;3.当broker是多台机器时，则状态之间需要同步<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><br />
4.5.1&nbsp;<span class="Apple-style-span" style="color: #2e4a8e; font-size: 18px; font-weight: bold; ">Message delivery semantics</span><br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">So clearly there are multiple possible message delivery guarantees that could be provided :&nbsp;</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">at most once 、at least once、exactly once。<br />
&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">This problem is heavily studied, and is a variation of the "transaction commit" problem. Algorithms that provide exactly once semantics exist, two- or three-phase commits and Paxos variants being examples, but they come with some drawbacks. They typically require multiple round trips and may have poor guarantees of liveness (they can halt indefinitely).&nbsp;<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp; 消费分发语义，是 &#8216;事务提交&#8217; 问题的变种。算法提供 exactly onece 语义，两阶段 or 三阶段提交，paxos 均是例子，但它们存在缺点。典型的问题是要求多次round trip，且
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">poor guarantees of liveness。<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">Kafka does two unusual things with respect to metadata.&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">First the stream is partitioned on the brokers into a set of distinct partitions.&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">Within a partition messages are stored in the order in which they arrive at the broker, and will be given out to consumers in that same order. </span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: yellow; ">This means that rather than store metadata for each message (marking it as consumed, say), we just need to store the "high water mark" for each combination of consumer, topic, and partition.</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><br />
</span><span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; ">&nbsp; &nbsp;&nbsp;<br />
<span class="Apple-style-span" style="font-size: 15px; ">4.5.2&nbsp;</span></span><span class="Apple-style-span" style="color: #2e4a8e; font-family: Arial, sans-serif; font-size: 18px; font-weight: bold; line-height: 22px; background-color: #ffffff; ">Consumer state</span><span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; "><span class="Apple-style-span" style="font-size: 15px; "><br />
</span></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;In Kafka, the consumers are responsible for maintaining state information (offset) on what has been consumed.</span><span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; "><span class="Apple-style-span" style="font-size: 15px; ">&nbsp;
<div style="display: inline-block; "></div>
</span></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">Typically, the Kafka consumer library writes their state data to zookeeper.<br />
</span><span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; ">&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: yellow; ">This solves a distributed consensus problem, by removing the distributed part!</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><br />
</span><span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; ">&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">There is a side benefit of this decision. A consumer can deliberately&nbsp;<em>rewind</em>&nbsp;back to an old offset and re-consume data.<br />
</span><span style="color: #222222; font-family: Arial, sans-serif; line-height: 22px; "><br />
4.5.3&nbsp;<span class="Apple-style-span" style="color: #2e4a8e; font-size: 18px; font-weight: bold; background-color: #ffffff; ">Push vs. pull</span><br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">A related question is whether consumers should pull data from brokers or brokers should push data to the subscriber.
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">There are pros and cons to both approaches.</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;However a push-based system has difficulty dealing with diverse consumers as the broker controls the rate at which data is transferred. push目标是consumer能在最大速率去消费，可不幸的是，当consume速率小于生产速率时，<span class="Apple-style-span" style="font-size: 14px; ">the consumer tends to be overwhelmed。<br />
</span>&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">A pull-based system has the nicer property that the consumer simply falls behind and catches up when it can. This can be mitigated with some kind of backoff protocol by which the consumer can indicate it is overwhelmed, but getting the rate of transfer to fully utilize (but never over-utilize) the consumer is trickier than it seems. Previous attempts at building systems in this fashion led us to go with a more traditional pull model. &nbsp;不存在push问题，且也保证充分利用consumer能力。<br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><br />
5.&nbsp;<span class="Apple-style-span" style="color: #2e4a8e; font-size: 23px; font-weight: bold; ">Distribution</span><br />
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;Kafka is built to be run across a cluster of machines as the common case. There is no central "master" node. Brokers are peers to each other and can be added and removed at anytime without any manual configuration changes. Similarly, producers and consumers can be started dynamically at any time. Each broker registers some metadata (e.g., available topics) in Zookeeper. Producers and consumers can use Zookeeper to discover topics and to co-ordinate the production and consumption. The details of producers and consumers will be described below.<br />
</span><span class="Apple-style-span" style="font-family: Arial, sans-serif; line-height: 22px; background-color: #ffffff; "><br />
<font class="Apple-style-span" color="#222222"><span class="Apple-style-span" style="font-size: 15px;">6.&nbsp;</span></font><font class="Apple-style-span" color="#2e4a8e"><span class="Apple-style-span" style="font-size: 23px;"><strong>Producer<br />
</strong></span></font><font class="Apple-style-span" color="#222222"><span class="Apple-style-span" style="font-size: 15px;"><br />
</span></font></span><span class="Apple-style-span" style="font-family: Arial, sans-serif; line-height: 22px; background-color: #ffffff; "><font class="Apple-style-span" color="#222222"><span class="Apple-style-span" style="font-size: 15px;">6.1&nbsp;</span></font><span class="Apple-style-span" style="color: #2e4a8e; font-size: 18px; font-weight: bold; ">Automatic producer load balancing<br />
</span></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;Kafka supports client-side load balancing for message producers or use of a dedicated load balancer to balance TCP connections.&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;The advantage of using a level-4 load balancer is that each producer only needs a single TCP connection, and no connection to zookeeper is needed.&nbsp;
<div style="display: inline-block; "></div>
</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">The disadvantage is that the balancing is done at the TCP connection level, and hence it may not be well balanced (if some producers produce many more messages then others, evenly dividing up the connections per broker may not result in evenly dividing up the messages per broker).<br />
</span><span class="Apple-style-span" style="font-family: Arial, sans-serif; line-height: 22px; background-color: #ffffff; "><span class="Apple-style-span" style="color: #2e4a8e; font-size: 18px; font-weight: bold; ">&nbsp; &nbsp;&nbsp;
<div style="display: inline-block; "></div>
</span></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">Client-side zookeeper-based load balancing solves some of these problems. It allows the producer to dynamically discover new brokers, and balance load on a per-request basis.&nbsp;I</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">t allows the producer to partition data according to some key instead of randomly.</span><span class="Apple-style-span" style="font-family: Arial, sans-serif; line-height: 22px; background-color: #ffffff; "><span class="Apple-style-span" style="color: #2e4a8e; font-size: 18px; font-weight: bold; "><br />
</span></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">
<p>&nbsp;&nbsp;&nbsp;&nbsp;The working of the zookeeper-based load balancing is described below. Zookeeper watchers are registered on the following events&#8212;</p>
<ul>
     <li>a new broker comes up</li>
     <li>a broker goes down</li>
     <li>a new topic is registered</li>
     <li>a broker gets registered for an existing topic</li></ul></span><p>&nbsp;&nbsp;&nbsp;&nbsp;Internally, the producer maintains an elastic pool of connections to the brokers, one per broker. <span style="background-color: yellow; ">This pool is kept updated to establish/maintain connections to all the live brokers, through the zookeeper watcher callbacks</span>. When a producer request for a particular topic comes in, a broker partition is picked by the partitioner (see section on semantic partitioning). The available producer connection is used from the pool to send the data to the selected broker partition.<br />
&nbsp; &nbsp; producer通过zk，管理与broker的连接。当一个请求，根据partition rule 计算分区，从连接池选择对应的connection，发送数据。<br />
<br />
6.2 <span class="Apple-style-span" style="color: #2e4a8e; font-family: Arial, sans-serif; font-size: 18px; font-weight: bold; line-height: 22px; background-color: #ffffff; ">Asynchronous send</span></p>
<span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;Asynchronous non-blocking operations are fundamental to scaling messaging systems.<br />&nbsp; &nbsp;&nbsp;<div style="display: inline-block; "></div></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">This allows buffering of produce requests in a in-memory queue and batch sends that are triggered by a time interval or a pre-configured batch size.&nbsp;<br /></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><br />6.3&nbsp;<span class="Apple-style-span" style="color: #2e4a8e; font-size: 18px; font-weight: bold; ">Semantic partitioning<br /></span>&nbsp; &nbsp;&nbsp;<div style="display: inline-block; "></div></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">The producer has the capability to be able to semantically map messages to the available kafka nodes and partitions.&nbsp;<div style="display: inline-block; "></div></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; ">This allows partitioning the stream of messages with some semantic partition function based on some key in the message to spread them over broker machines.&nbsp;</span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><br /><br /></span><span class="Apple-style-span" style="color: #222222; font-family: Arial, sans-serif; font-size: 15px; line-height: 22px; background-color: #ffffff; "><div>
<br />
</div>
</span></div><img src ="http://www.blogjava.net/shijian/aggbug/378641.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2013-07-06 14:57 <a href="http://www.blogjava.net/shijian/archive/2013/07/06/378641.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Js练习：操纵cookie</title><link>http://www.blogjava.net/shijian/archive/2012/09/09/387339.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Sun, 09 Sep 2012 07:18:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2012/09/09/387339.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/387339.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2012/09/09/387339.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/387339.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/387339.html</trackback:ping><description><![CDATA[<p style="margin: 4px 0px; padding: 2px 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: normal; background-color: #ffffff; ">1.Js代码，login.js文件<br /><br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">用户的登陆信息写入cookies</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">function</span>&nbsp;SetCookie(form)<span style="color: #008000; ">//</span><span style="color: #008000; ">两个参数，一个是cookie的名子，一个是值</span><span style="color: #008000; "><br /></span>{&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;name&nbsp;=&nbsp;form.name.value;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;password&nbsp;=&nbsp;form.password.value;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;Days&nbsp;=&nbsp;1;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">此&nbsp;cookie&nbsp;将被保存&nbsp;7&nbsp;天&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;exp&nbsp;&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Date();&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">生成一个现在的日期，加上保存期限，然后设置cookie的生存期限！</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;exp.setTime(exp.getTime()&nbsp;+&nbsp;Days*24*60*60*1000);<br />&nbsp;&nbsp;&nbsp;&nbsp;document.cookie&nbsp;=&nbsp;"user="+&nbsp;escape(name)&nbsp;+&nbsp;"/"&nbsp;+&nbsp;escape(password)&nbsp;+&nbsp;";expires="&nbsp;+&nbsp;exp.toGMTString();<br />}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">取cookies函数--正则表达式(不会，学习正则表达式)&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">function</span>&nbsp;getCookie(name)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;arr&nbsp;=&nbsp;document.cookie.match(<span style="color: #0000FF; ">new</span>&nbsp;RegExp("(^|&nbsp;)"+name+"=([^;]*)(;|$)"));<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(arr&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;unescape(arr[2]);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">取cookies函数--普通实现&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;<span style="color: #0000FF; ">function</span>&nbsp;&nbsp;&nbsp;readCookie(form){&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;&nbsp;&nbsp;cookieValue&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;"";&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;&nbsp;&nbsp;search&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;"user=";&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(document.cookie.length&nbsp;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&nbsp;0)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;document.cookie.indexOf(search);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(offset&nbsp;!=&nbsp;&nbsp;-1){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;offset&nbsp;&nbsp;&nbsp;+=&nbsp;&nbsp;&nbsp;search.length;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;document.cookie.indexOf(";",offset);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;&nbsp;&nbsp;(end&nbsp;&nbsp;==&nbsp;&nbsp;-1)&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;document.cookie.length;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">获取cookies里面的值&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cookieValue&nbsp;&nbsp;&nbsp;=&nbsp;&nbsp;&nbsp;unescape(document.cookie.substring(offset,end))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(cookieValue&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;str&nbsp;=&nbsp;cookieValue.split("/");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;form.name.value&nbsp;=&nbsp;str[0];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;form.password.value&nbsp;=&nbsp;str[1];&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">删除cookie，（servlet里面：设置时间为0，设置为-1和session的范围是一样的），javascript好像是有点区别</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">function</span>&nbsp;delCookie()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;name&nbsp;=&nbsp;"admin";<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;exp&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Date();<br />&nbsp;&nbsp;&nbsp;&nbsp;exp.setTime(exp.getTime()&nbsp;-&nbsp;1);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">var</span>&nbsp;cval=getCookie(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(cval!=<span style="color: #0000FF; ">null</span>)&nbsp;document.cookie=&nbsp;name&nbsp;+&nbsp;"="+cval+";expires="+exp.toGMTString();<br />}</div><br /><p>&nbsp;</p><p style="margin: 4px 0px; padding: 2px 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: normal; background-color: #ffffff; "><span style="background-color: #f8f8f8; ">2.jsp代码，文件login.jsp</span><span style="color: #0000ff; background-color: #f8f8f8; "><br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&lt;%@&nbsp;page&nbsp;contentType="text/html;&nbsp;charset=gb2312"&nbsp;language="java"<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">import</span>="java.sql.*"&nbsp;errorPage=""%&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&lt;html&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;head&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;meta&nbsp;http-equiv="Content-Type"&nbsp;content="text/html;&nbsp;charset=gb2312"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;javascript&nbsp;控制&nbsp;cookie&lt;/title&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;link&nbsp;href="css/style.css"&nbsp;rel="stylesheet"&nbsp;type="text/css"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;script&nbsp;type="text/javascript"&nbsp;src="js/login.js"&gt;&lt;/script&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/head&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;script&nbsp;language="javascript"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;checkEmpty(form){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(i=0;i&lt;form.length;i++){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(form.elements[i].value==""){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert("表单信息不能为空");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">false</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&lt;/script&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;body&nbsp;onload="readCookie(form)"&gt;&nbsp;&lt;!--&nbsp;作为JavaScript控制的cookie--&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div&nbsp;align="center"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;table&nbsp;width="324"&nbsp;height="225"&nbsp;border="0"&nbsp;cellpadding="0"&nbsp;cellspacing="0"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&nbsp;height="50"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;&gt;&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&nbsp;align="center"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;background="images/back.jpg"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;br&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;br&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;登陆<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;form&nbsp;name="form"&nbsp;method="post"&nbsp;action=""&nbsp;onSubmit="return&nbsp;checkEmpty(form)"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type="hidden"&nbsp;name="id"&nbsp;value="-1"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;table&nbsp;width="268"&nbsp;border="1"&nbsp;cellpadding="0"&nbsp;cellspacing="0"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&nbsp;align="center"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;width="63"&nbsp;height="30"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用户名：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;width="199"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type="text"&nbsp;name="name"&nbsp;id="name"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&nbsp;align="center"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;height="30"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;密码：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type="password"&nbsp;name="password"&nbsp;id="password"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/table&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;br&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type="submit"&nbsp;value="提交"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input&nbsp;type="checkbox"&nbsp;name="cookie"&nbsp;onclick="SetCookie(form)"&gt;记住我&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/form&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/table&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;/body&gt;<br />&lt;/html&gt;</div><p>&nbsp;</p><div style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: normal; background-color: #ffffff; "><p style="margin: 4px 0px; padding: 2px 0px; "><br />目的：当你再次打开login.jsp页面，表单里面的内容已经写好了，是你上一次的登陆信息！</p></div><div style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: normal; background-color: #ffffff; "><br />问题：1.JavaScript里面取cookie都是写死的，不是很灵活！</div><div style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: normal; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.JavaScript的cookie是按照字符串的形式存放的，所以拿出的时候，你要按照你放进去的形式来选择！</div><div style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: normal; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.本来是想实现自动登陆的，可我的每个页面都要session的检查！一个客户端，一个服务器端，没能实现！</div><p style="margin: 4px 0px; padding: 2px 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: normal; background-color: #ffffff; ">&nbsp;</p><p style="margin: 4px 0px; padding: 2px 0px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; line-height: normal; background-color: #ffffff; ">&nbsp;</p><img src ="http://www.blogjava.net/shijian/aggbug/387339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2012-09-09 15:18 <a href="http://www.blogjava.net/shijian/archive/2012/09/09/387339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单元测试利器 之 powermock [使用小结]</title><link>http://www.blogjava.net/shijian/archive/2012/03/29/371819.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Thu, 29 Mar 2012 04:39:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2012/03/29/371819.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/371819.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2012/03/29/371819.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/371819.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/371819.html</trackback:ping><description><![CDATA[<br />官方 ：<a href="http://code.google.com/p/powermock/">http://code.google.com/p/powermock/</a>&nbsp; <br /><br />1. 使用mockito的同学，推荐阅读如下部分<br /><br /><div><span class="Apple-style-span" style="font-family: arial, sans-serif; line-height: normal; font-size: small; ">&nbsp; &nbsp; - document [必选]</span><div><font class="Apple-style-span" size="2"><span class="Apple-style-span" style="line-height: normal; "><font class="Apple-style-span" face="arial, sans-serif">&nbsp; &nbsp; &nbsp; &nbsp; - getting started</font><br /><font class="Apple-style-span" face="arial, sans-serif">&nbsp; &nbsp; &nbsp; &nbsp; - motavition</font><br /><font class="Apple-style-span" face="arial, sans-serif">&nbsp; &nbsp; - mockito extends [必选]</font><br /><font class="Apple-style-span" face="arial, sans-serif">&nbsp; &nbsp; &nbsp; &nbsp; - mockito 1.8+ useage</font><br /><font class="Apple-style-span" face="arial, sans-serif">&nbsp; &nbsp; - common</font><br /><font class="Apple-style-span" face="arial, sans-serif">&nbsp; &nbsp; - tutorial</font><br /><font class="Apple-style-span" face="arial, sans-serif">&nbsp; &nbsp; - faq [必选]</font><br /><br /></span></font><span class="Apple-style-span" style="line-height: normal; font-size: small; "><span style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: yellow; "><font class="Apple-style-span" face="arial, sans-serif"><br /></font><font class="Apple-style-span" face="宋体">2. 附件：实际开发中使用到的</font></span><span style="font-family: arial, sans-serif; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: yellow; background-position: initial initial; background-repeat: initial initial; ">powermock</span><span style="font-family: 宋体; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: yellow; background-position: initial initial; background-repeat: initial initial; ">的一些特性，简化后的例子（仅为说明</span><span style="font-family: arial, sans-serif; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: yellow; background-position: initial initial; background-repeat: initial initial; ">powermock api</span><span style="font-family: 宋体; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: yellow; background-position: initial initial; background-repeat: initial initial; ">使用）</span><span style="font-family: 宋体; ">。主要包括</span> <span style="font-family: 宋体; ">：</span></span><font class="Apple-style-span" size="2"><span class="Apple-style-span" style="line-height: normal; "><br />  <p style="font-family: arial, sans-serif; margin-left: 18pt; ">&nbsp;</p>  <p style="font-family: arial, sans-serif; margin-left: 60pt; text-indent: -18pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family:宋体">修改私有域</span></p>  <p style="font-family: arial, sans-serif; margin-left: 60pt; text-indent: -18pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family:宋体">私有方法</span></p>  <p style="font-family: arial, sans-serif; margin-left: 84pt; text-indent: -21pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family:宋体">测试私有方法</span></p>  <p style="font-family: arial, sans-serif; margin-left: 84pt; text-indent: -21pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>Mock</p>  <p style="font-family: arial, sans-serif; margin-left: 84pt; text-indent: -21pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>Verify</p>  <p style="font-family: arial, sans-serif; margin-left: 60pt; text-indent: -18pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family:宋体">静态方法</span></p>  <p style="font-family: arial, sans-serif; margin-left: 84pt; text-indent: -21pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>Mock</p>  <p style="font-family: arial, sans-serif; margin-left: 84pt; text-indent: -21pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family:宋体">抛出异常</span></p>  <p style="font-family: arial, sans-serif; margin-left: 84pt; text-indent: -21pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>Verify</p>  <p style="font-family: arial, sans-serif; margin-left: 60pt; text-indent: -18pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>Mock<span style="font-family:宋体">类部分方法</span></p>  <p style="font-family: arial, sans-serif; margin-left: 60pt; text-indent: -18pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>Mock Java core library<span style="font-family:宋体">，如：</span>Thread</p>  <p style="font-family: arial, sans-serif; margin-left: 60pt; text-indent: -18pt; "><span><span>-<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span>Mock <span style="font-family:宋体">构造器<br /><br /><a href="/Files/shijian/powermock.rar">/Files/shijian/powermock.rar</a><br /><br /><br /></span></p><br /></span></font></div><a href="http://code.google.com/p/powermock/"></a></div><img src ="http://www.blogjava.net/shijian/aggbug/371819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2012-03-29 12:39 <a href="http://www.blogjava.net/shijian/archive/2012/03/29/371819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Annotation一点总结</title><link>http://www.blogjava.net/shijian/archive/2011/06/25/353002.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Sat, 25 Jun 2011 12:09:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2011/06/25/353002.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/353002.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2011/06/25/353002.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/353002.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/353002.html</trackback:ping><description><![CDATA[<p align="center" style="text-align:center"><strong><span style="font-size: 12pt; ">Annotation</span></strong></p>  <p align="center" style="text-align:center"><strong>&nbsp;</strong></p>  <p><em><span style="font-family: 宋体; font-size: 10pt; ">题记：建议关于</span></em><em style="font-size: 10pt; ">spring</em><em><span style="font-family:宋体;">问题，请记得查看</span>spring reference</em><em><span style="font-family:宋体;">。</span></em></p>  <p>&nbsp;</p>  <p><span style="font-family: 宋体; font-size: 10pt; ">一、</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">前生后世</span></p>  <p><span style="font-size: 10pt; ">Annotations do not directly affect program semantics, but they do affect the way programs are treated by tools and libraries, which can in turn affect the semantics of the running program. Annotations can be read from source files, class files, or reflectively at run time.</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">译：</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">不会直接影响程序的语义，</span><span style="font-size: 10pt; ">xxx</span><span style="font-family: 宋体; font-size: 10pt; ">。</span><span style="font-size: 10pt; ">Annotation</span><span style="font-family: 宋体; font-size: 10pt; ">可以从源文件、</span><span style="font-size: 10pt; ">class</span><span style="font-family: 宋体; font-size: 10pt; ">文件、通过反射在运行时读取。</span></p>  <p>&nbsp;</p>  <p><span style="font-family: 宋体; font-size: 10pt; ">参考：</span><a href="http://www.developer.com/print.php/3556176"><span style="font-size: 10pt; ">http://www.developer.com/print.php/3556176</span></a></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span><span style="font-size: 10pt; ">1.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体; font-size: 10pt; ">定义</span></p>  <p><span style="font-size: 10pt; ">Annotation type declarations are similar to normal interface declarations. An at-sign (@) precedes the&nbsp;interface&nbsp;keyword. Each method declaration defines an&nbsp;element&nbsp;of the annotation type. Method declarations must not have any parameters or a&nbsp;throws&nbsp;clause. Return types are restricted to primitives,&nbsp;<a href="http://download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html"><span style="color: windowtext; text-decoration: none; font-size: 10pt; ">String</span></a></span><span style="font-size: 10pt; ">,&nbsp;<a href="http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html"><span style="color: windowtext; text-decoration: none; font-size: 10pt; ">Class</span></a></span><span style="font-size: 10pt; ">,&nbsp;<a href="http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html"><span style="color: windowtext; text-decoration: none; font-size: 10pt; ">enums</span></a></span><span style="font-size: 10pt; ">, annotations, and arrays of the preceding types. Methods can have&nbsp;default values.</span></p>  <p><span style="font-size: 10pt; ">Annotation</span><span style="font-family: 宋体; font-size: 10pt; ">声明与普通的</span><span style="font-size: 10pt; ">interface</span><span style="font-family: 宋体; font-size: 10pt; ">非常相似，在关键字</span><span style="font-size: 10pt; ">interface</span><span style="font-family: 宋体; font-size: 10pt; ">前加</span><span style="font-size: 10pt; ">@</span><span style="font-family: 宋体; font-size: 10pt; ">。每一个方法的声明定义一个</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">的元素。方法不能有任何的参数或</span><span style="font-size: 10pt; ">throws</span><span style="font-family: 宋体; font-size: 10pt; ">异常。返回类型被限制为：原始类型、</span><span style="font-size: 10pt; ">String</span><span style="font-family: 宋体; font-size: 10pt; ">、</span><span style="font-size: 10pt; ">Class</span><span style="font-family: 宋体; font-size: 10pt; ">、</span><span style="font-size: 10pt; ">enum</span><span style="font-family: 宋体; font-size: 10pt; ">、</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">、前面描述的类型组成的数组。</span><span style="font-size: 10pt; ">method</span><span style="font-family: 宋体; font-size: 10pt; ">定义允许有默认值。</span></p>  <p>&nbsp;</p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span><span style="font-size: 10pt; ">2.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt; ">Java annotation</span></p>  <p align="left" style="text-align:left;"><span style="font-size: 10pt; ">There are two types of annotations available with JDK5:</span></p>  <p align="left" style="margin-left:18.0pt;text-align:left; text-indent:-18.0pt;"><span style="font-size: 10pt; ">1）&nbsp;</span><span style="font-size: 10pt; ">Simple annotations:&nbsp;These are the basic types supplied with Tiger, which you can use to annotate your code only; you cannot use those to create a custom annotation type.</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">三个基本的</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">，如：</span><span style="font-size: 10pt; ">Override</span><span style="font-family: 宋体; font-size: 10pt; ">、</span><span style="font-size: 10pt; ">Deprecated</span><span style="font-family: 宋体; font-size: 10pt; ">、</span><span style="font-size: 10pt; ">Suppresswarnings</span><span style="font-family: 宋体; font-size: 10pt; ">，不能使用它去定义新的</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">。</span></p>  <p align="left" style="margin-top:0cm;margin-right:12.0pt; margin-bottom:0cm;margin-left:18.0pt;margin-bottom:.0001pt;text-align:left; text-indent:-18.0pt;"><span style="font-size: 10pt; ">2）&nbsp;</span><span style="font-size: 10pt; ">Meta annotations:&nbsp;These are the annotation types designed for annotating annotation-type declarations. Simply speaking, these are called the annotations-of-annotations.</span></p>  <p align="left" style="margin-top:0cm;margin-right:12.0pt; margin-bottom:0cm;margin-left:18.0pt;margin-bottom:.0001pt;text-align:left; text-indent:0cm;"><span style="font-family: 宋体; font-size: 10pt; ">元</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">，定义</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">的类型。如：</span><span><span style="font-family: Arial, sans-serif; color: black; font-size: 10pt; ">Target</span></span><span style="font-family: 宋体; color: black; font-size: 10pt; ">、</span><span><span style="font-family: Arial, sans-serif; color: black; font-size: 10pt; ">Retention</span></span><span style="font-family: 宋体; color: black; font-size: 10pt; ">、</span><span><span style="font-family: Arial, sans-serif; color: black; font-size: 10pt; ">Documented</span></span><span style="font-family: 宋体; color: black; font-size: 10pt; ">、</span><span><span style="font-family: Arial, sans-serif; color: black; font-size: 10pt; ">Inherited</span></span><span style="font-family: 宋体; color: black; font-size: 10pt; ">。</span></p>  <p align="left" style="margin-top:0cm;margin-right:12.0pt; margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;text-align:left; text-indent:-18.0pt;"><span><span><span style="font-size: 10pt; ">A.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span></span><span style="font-size: 10pt; ">Target</span><span style="font-family: 宋体; font-size: 10pt; ">：声明</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">注解的目标类型。如</span><span><span style="font-family: 'Courier New'; color: black; font-size: 10pt; ">@Target(ElementType.TYPE)</span></span><span><span style="font-family: 宋体; font-size: 10pt; ">、</span></span><span style="font-family: 'Courier New'; color: black; font-size: 10pt; ">@Target(ElementType.METHOD)</span></p>  <p align="left" style="margin-top:0cm;margin-right:12.0pt; margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;text-align:left; text-indent:-18.0pt;"><span><span style="font-size: 10pt; ">B.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt; ">Retention</span><span style="font-family: 宋体; font-size: 10pt; ">：声明</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">被保留的长度。如：</span><span style="font-size: 10pt; ">RetentionPolicy.SOURCE</span><span style="font-family: 宋体; font-size: 10pt; ">、</span><span style="font-size: 10pt; ">RetentionPolicy.CLASS</span><span style="font-family: 宋体; font-size: 10pt; ">、</span><span style="font-size: 10pt; ">RetentionPolicy.RUNTIME</span></p>  <p align="left" style="margin-top:0cm;margin-right:12.0pt; margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;text-align:left; text-indent:-18.0pt;"><span><span style="font-size: 10pt; ">C.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: Arial, sans-serif; color: black; font-size: 10pt; ">D</span><span style="font-size: 10pt; ">ocumented</span><span style="font-family: 宋体; font-size: 10pt; ">：声明被注解的</span><span style="font-size: 10pt; ">target</span><span style="font-family: 宋体; font-size: 10pt; ">生成</span><span style="font-size: 10pt; ">doc</span><span style="font-family: 宋体; font-size: 10pt; ">是否需要显示</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">信息。</span> </p>  <p align="left" style="margin-top:0cm;margin-right:12.0pt; margin-bottom:0cm;margin-left:36.0pt;margin-bottom:.0001pt;text-align:left; text-indent:-18.0pt;"><span><span style="font-size: 10pt; ">D.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: Arial, sans-serif; color: black; font-size: 10pt; ">Inherited</span><span style="font-family: 宋体; color: black; font-size: 10pt; ">：</span><span><span style="font-family: Arial, sans-serif; color: black; font-size: 10pt; ">xxx</span></span></p>  <p align="left" style="margin-right:12.0pt;text-align:left;">&nbsp;</p>  <p align="left" style="margin-top:0cm;margin-right:12.0pt; margin-bottom:0cm;margin-left:18.0pt;margin-bottom:.0001pt;text-align:left; text-indent:-18.0pt;"><span><span style="font-size: 10pt; ">3.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">作用</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span style="font-size: 10pt; ">a．&nbsp;</span><span style="font-family: 宋体; font-size: 10pt; ">不影响程序原本语义的情况下，增加信息</span><span style="font-size: 10pt; ">+</span><span style="font-family: 宋体; font-size: 10pt; ">工具</span><span style="font-size: 10pt; ">=</span><span style="font-family: 宋体; font-size: 10pt; ">声明式编程。如：</span><span style="font-size: 10pt; ">spring aop</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span style="font-size: 10pt; ">b．&nbsp;</span><span style="font-family: 宋体; font-size: 10pt; ">编译检查</span> <span style="font-family: 宋体; font-size: 10pt; ">？</span></p>  <p>&nbsp;</p>  <p>&nbsp;</p>  <p><span style="font-family: 宋体; font-size: 10pt; ">二、利用</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">实现</span><span style="font-size: 10pt; ">aop</span></p>  <p><span style="font-size: 10pt; ">1. </span><span style="font-family: 宋体; font-size: 10pt; ">思路</span></p>  <p><span style="font-size: 10pt; ">A</span><span style="font-family: 宋体; font-size: 10pt; ">．自定义注解定义规则（何时执行）</span></p>  <p><span style="font-size: 10pt; ">B</span><span style="font-family: 宋体; font-size: 10pt; ">．标记行为（执行什么）</span></p>  <p><span style="font-size: 10pt; ">C</span><span style="font-family: 宋体; font-size: 10pt; ">．通过反射生成代理，在对象执行任何方法时，进行拦截判断是否符合规则；若符合，执行对应的行为。</span></p>  <p><span style="font-size: 10pt; ">2. </span><span style="font-family: 宋体; font-size: 10pt; ">例子</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">场景：一个表演家，表演节目后，观众拍手鼓掌</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">原始：表演家拥有所有观众的引用，在自己表演完后，通知观众鼓掌</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">问题：表演家应该关注表演自身的事情，有哪些观众、观众是否鼓掌，不是其所关注的</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">改进：</span><span style="font-size: 10pt; ">AOP</span><span style="font-family: 宋体; font-size: 10pt; ">方式，表演家仅关注表演，观众鼓掌由其它人负责</span></p>  <p><em><span style="font-family: 宋体; font-size: 10pt; ">总结：</span> </em></p>  <p style="text-indent:21.0pt"><span><em><span style="font-family: 宋体; color: #222222; font-size: 10pt; ">面向切面编程</span></em></span><em><span style="color: #222222; font-size: 10pt; "> (AOP) </span></em><span><em><span style="font-family: 宋体; color: #222222; font-size: 10pt; ">提供从另一个角度来考虑程序结构以完善面向对象编程（</span></em></span><em><span style="color: #222222; font-size: 10pt; ">OOP</span></em><span><em><span style="font-family: 宋体; color: #222222; font-size: 10pt; ">）。</span></em></span><em> </em><span><em><span style="font-family: 宋体; color: #222222; font-size: 10pt; ">面向对象将应用程序分解成各个层次的对象，而</span></em></span><em><span style="color: #222222; font-size: 10pt; ">AOP</span></em><span><em><span style="font-family: 宋体; color: #222222; font-size: 10pt; ">将程序分解成各个切面或者说关注点。这使得可以模块化诸如事务管理等这些横切多个对象的关注点。</span></em></span></p>  <p>&nbsp;</p>  <p><span style="font-family: 宋体; font-size: 10pt; ">三、</span><span style="font-size: 10pt; ">spring&nbsp;aop</span><span style="font-family: 宋体; font-size: 10pt; ">如何使用</span><span style="font-size: 10pt; ">annotation</span></p>  <p><span style="font-size: 10pt; ">1. </span><span style="font-family: 宋体; font-size: 10pt; ">基本方式，通过</span><span style="font-size: 10pt; ">ProxyFactoryBean</span></p>  <p style="text-indent:21.0pt"><span style="font-size: 10pt; ">a</span><span style="font-family: 宋体; font-size: 10pt; ">．通知</span></p>  <p style="text-indent:21.0pt"><span style="font-size: 10pt; ">b</span><span style="font-family: 宋体; font-size: 10pt; ">．切入点</span></p>  <p style="text-indent:21.0pt"><span style="font-size: 10pt; ">b</span><span style="font-family: 宋体; font-size: 10pt; ">．通知</span><span style="font-size: 10pt; ">+</span><span style="font-family: 宋体; font-size: 10pt; ">切入点</span> <span style="font-family: Wingdings; font-size: 10pt; ">&#224;</span> <span style="font-family: 宋体; font-size: 10pt; ">切面</span></p>  <p style="text-indent:21.0pt"><span style="font-size: 10pt; ">c</span><span style="font-family: 宋体; font-size: 10pt; ">．实际对象</span><span style="font-size: 10pt; ">+</span><span style="font-family: 宋体; font-size: 10pt; ">接口</span><span style="font-size: 10pt; ">+</span><span style="font-family: 宋体; font-size: 10pt; ">切面</span> <span style="font-family: Wingdings; font-size: 10pt; ">&#224;</span> <span style="font-family: 宋体; font-size: 10pt; ">接口代理（）</span></p>  <p><span style="font-size: 10pt; ">2. </span><span style="font-family: 宋体; font-size: 10pt; ">自动代理方式：</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">基本方式的问题是，</span><span style="font-size: 10pt; ">xml</span><span style="font-family: 宋体; font-size: 10pt; ">配置文件繁琐。</span></p>  <p><span style="font-size: 10pt; ">1</span><span style="font-family: 宋体; font-size: 10pt; ">）基于</span><span style="font-size: 10pt; ">spring</span><span style="font-family: 宋体; font-size: 10pt; ">上下文的通知者</span><span style="font-size: 10pt; ">Bean</span><span style="font-family: 宋体; font-size: 10pt; ">的自动代理（利用</span><span style="font-size: 10pt; ">PostBeanProcessor </span><span style="font-family: 宋体; font-size: 10pt; ">？）</span></p>  <p style="text-indent:21.0pt"><span style="font-size: 10pt; ">BeanNameAutoProxyCreator</span><span style="font-family: 宋体; font-size: 10pt; ">，有属性：</span><span style="font-size: 10pt; ">beanNames</span><span style="font-family: 宋体; font-size: 10pt; ">（被代理对象）、</span><span style="font-size: 10pt; ">interceptorNames</span><span style="font-family: 宋体; font-size: 10pt; ">（通知）。自动代理</span><span style="font-size: 10pt; ">beanNames</span><span style="font-family: 宋体; font-size: 10pt; ">指定的</span><span style="font-size: 10pt; ">bean</span><span style="font-family: 宋体; font-size: 10pt; ">，此时</span><span style="font-size: 10pt; ">interceptorNames</span><span style="font-family: 宋体; font-size: 10pt; ">指定通知，但</span><span style="font-size: 10pt; ">interceptor</span><span style="font-family: 宋体; font-size: 10pt; ">需要实现特定的接口，如：</span><span style="font-size: 10pt; ">MethodBeforeAdvice</span><span style="font-family: 宋体; font-size: 10pt; ">。</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span style="font-size: 10pt; ">2）&nbsp;</span><span style="font-family: 宋体; font-size: 10pt; ">基于</span><span style="font-size: 10pt; ">aspectJ</span><span style="font-family: 宋体; font-size: 10pt; ">注解驱动</span></p>  <p style="margin-left:18.0pt"><span style="font-family: 宋体; font-size: 10pt; ">使用</span><span style="font-size: 10pt; ">aspectJ</span><span style="font-family: 宋体; font-size: 10pt; ">风格的注解。原理：生成代理，仅方法级别。使用</span><span style="font-size: 10pt; ">AspectJ </span><span style="font-family: 宋体; font-size: 10pt; ">提供的一个库来做切点（</span><span style="font-size: 10pt; ">pointcut</span><span style="font-family: 宋体; font-size: 10pt; ">）解析和匹配。</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span><span style="font-size: 10pt; ">4.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt; ">&lt;aop:config&gt;</span><span style="font-family: 宋体; font-size: 10pt; ">，优点：任何类都能转化为切面，不需要特殊接口或注解，原始</span><span style="font-size: 10pt; ">pojo</span><span style="font-family: 宋体; font-size: 10pt; ">对象</span></p>  <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span><span style="font-size: 10pt; ">5.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 10pt; ">aop</span><span style="font-family: 宋体; font-size: 10pt; ">参数传递，见：</span><span style="font-size: 10pt; ">spring reference&nbsp;6.3.3.6 </span><span style="font-family: 宋体; font-size: 10pt; ">通知参数</span></p>  <p style="margin-left:36.0pt;text-indent:-18.0pt;"><span style="font-size: 10pt; ">a．&nbsp;</span><span style="font-size: 10pt; ">around</span><span style="font-family: 宋体; font-size: 10pt; ">切点，必须传递</span><span style="font-size: 10pt; ">ProceedingJoinPoint</span><span style="font-family: 宋体; font-size: 10pt; ">参数，通过</span><span style="font-size: 10pt; ">ProceedingJoinPoint</span><span style="font-family: 宋体; font-size: 10pt; ">取得方法的所有信息。</span></p>  <p style="margin-left:36.0pt;text-indent:-18.0pt;"><span style="font-size: 10pt; ">b．&nbsp;</span><span style="font-family: 宋体; font-size: 10pt; ">其它切点，利用</span><span style="font-size: 10pt; ">JoinPoint</span><span style="font-family: 宋体; font-size: 10pt; ">取得方法的所有参数。</span></p>  <p style="margin-left:36.0pt;text-indent:-18.0pt;"><span style="font-size: 10pt; ">c．&nbsp;</span><em><span style="font-family: 宋体; font-size: 10pt; ">通过参数名绑定传递参数，未理解</span></em><span style="font-family: 宋体; font-size: 10pt; ">。</span></p>  <p>&nbsp;</p>  <p>&nbsp;</p>  <p><span style="font-family: 宋体; font-size: 10pt; ">四、</span><span style="font-size: 10pt; ">annotation</span><span style="font-family: 宋体; font-size: 10pt; ">相关技术</span></p>  <p><span style="font-size: 10pt; ">1.&nbsp;cglib</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">它的原理就是用</span><span style="font-size: 10pt; ">Enhancer</span><span style="font-family: 宋体; font-size: 10pt; ">生成一个原有类的子类，并且设置好</span><span style="font-size: 10pt; ">callback</span><span style="font-family: 宋体; font-size: 10pt; ">到</span><span style="font-size: 10pt; ">proxy</span><span style="font-family: 宋体; font-size: 10pt; ">，</span> <span style="font-family: 宋体; font-size: 10pt; ">则原有类的每个方法调用都会转为调用实现了</span><span style="font-size: 10pt; ">MethodInterceptor</span><span style="font-family: 宋体; font-size: 10pt; ">接口的</span><span style="font-size: 10pt; ">proxy</span><span style="font-family: 宋体; font-size: 10pt; ">的</span><span style="font-size: 10pt; ">intercept()&nbsp;</span><span style="font-family: 宋体; font-size: 10pt; ">函数。</span></p>  <p><span style="font-size: 10pt; ">2. &nbsp;asm</span></p>  <p style="margin-top:7.5pt;margin-right:7.5pt;margin-bottom:3.75pt;margin-left: 0cm;line-height:12.0pt"><strong><span style="font-family: Calibri, sans-serif; font-size: 10pt; ">ASM</span></strong><span style="font-family: Calibri, sans-serif; font-size: 10pt; ">&nbsp;is an all purpose Java bytecode manipulation and analysis framework. It can be used to modify existing classes or dynamically generate classes, directly in binary form. Provided common transformations and analysis algorithms allow to easily assemble custom complex transformations and code analysis tools.</span></p>  <p style="margin-top:7.5pt;margin-right:7.5pt;margin-bottom:3.75pt;margin-left: 0cm;line-height:12.0pt"><span style="font-family: Calibri, sans-serif; font-size: 10pt; ">ASM offer similar functionality as other bytecode frameworks, but it is focused on simplicity of use and performance.&nbsp;</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">简单理解</span><span style="font-size: 10pt; ">asm</span><span style="font-family: 宋体; font-size: 10pt; ">是比</span><span style="font-size: 10pt; ">cglib</span><span style="font-family: 宋体; font-size: 10pt; ">更高级的</span><span style="font-size: 10pt; ">code generate lib</span><span style="font-family: 宋体; font-size: 10pt; ">。</span></p>  <p>&nbsp;</p>  <p><span style="font-family: 宋体; font-size: 10pt; ">五、</span><span style="font-size: 10pt; ">others</span><span style="font-family: 宋体; font-size: 10pt; ">问题</span></p>  <p><span style="font-size: 10pt; ">1.&nbsp;</span><a href="http://download.oracle.com/javase/1.5.0/docs/guide/language/generics.html"><span style="color: windowtext; text-decoration: none; font-size: 10pt; ">Generics</span></a>&nbsp;</p>  <p><a href="http://download.oracle.com/javase/1.5.0/docs/guide/language/generics.html"><span style="color: windowtext; text-decoration: none; font-size: 10pt; ">Generics</span></a><span style="font-size: 10pt; ">&nbsp;- This long-awaited enhancement to the type system allows a type or method to operate on objects of various types while providing compile-time type safety. It adds compile-time type safety to the Collections Framework and eliminates the drudgery of casting. See the</span><a href="http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf"><span style="color: windowtext; text-decoration: none; font-size: 10pt; ">Generics Tutorial</span></a><span style="font-size: 10pt; ">. (</span><a href="http://jcp.org/en/jsr/detail?id=14"><span style="color: windowtext; text-decoration: none; font-size: 10pt; ">JSR 14</span></a><span style="font-size: 10pt; ">)</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">泛型提供了编译时类型检查安全。这点很重要吗</span> <span style="font-family: 宋体; font-size: 10pt; ">？</span></p>  <p>&nbsp;</p>  <p><span style="font-size: 10pt; ">2. </span><span style="font-family: 宋体; font-size: 10pt; ">为什么</span><span style="font-size: 10pt; ">spring aop aspectJ anonotation</span><span style="font-family: 宋体; font-size: 10pt; ">的</span><span style="font-size: 10pt; ">pointcut</span><span style="font-family: 宋体; font-size: 10pt; ">声明，必须注解在方法上</span> <span style="font-family: 宋体; font-size: 10pt; ">？通过方法唯一标识一个</span><span style="font-size: 10pt; ">pointcut </span><span style="font-family: 宋体; font-size: 10pt; ">？</span></p>  <p><span style="font-family: 宋体; font-size: 10pt; ">猜测：</span><span style="font-size: 10pt; ">@Pointcut</span><span style="font-family: 宋体; font-size: 10pt; ">的</span><span style="font-size: 10pt; ">Target</span><span style="font-family: 宋体; font-size: 10pt; ">属性指定仅为</span><span style="font-size: 10pt; ">method</span><span style="font-family: 宋体; font-size: 10pt; ">。方法签名成为</span><span style="font-size: 10pt; ">pointcut</span><span style="font-family: 宋体; font-size: 10pt; ">的</span><span style="font-size: 10pt; ">id</span><span style="font-family: 宋体; font-size: 10pt; ">。</span></p>  <p><span style="font-size: 10pt; ">&nbsp;&nbsp;</span></p>  <p>&nbsp;</p><img src ="http://www.blogjava.net/shijian/aggbug/353002.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2011-06-25 20:09 <a href="http://www.blogjava.net/shijian/archive/2011/06/25/353002.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Reference思考</title><link>http://www.blogjava.net/shijian/archive/2010/12/18/341064.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Sat, 18 Dec 2010 08:52:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2010/12/18/341064.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/341064.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2010/12/18/341064.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/341064.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/341064.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;一、Java数据类型&nbsp;&nbsp;数据类型就是对内存位置的抽象表达（很多编程语言都依赖于特定的计算机类型和对数据类型属性的具体编译实现，比如word和integer数据类型的大小等；Java通过JVM保证数据所占存储空间的大小不会随硬件的改变发生变化）。1.&nbsp;&nbsp;&nbsp;Primitive data type ：A primiti...&nbsp;&nbsp;<a href='http://www.blogjava.net/shijian/archive/2010/12/18/341064.html'>阅读全文</a><img src ="http://www.blogjava.net/shijian/aggbug/341064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2010-12-18 16:52 <a href="http://www.blogjava.net/shijian/archive/2010/12/18/341064.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Proxy学习</title><link>http://www.blogjava.net/shijian/archive/2010/12/12/340380.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Sat, 11 Dec 2010 18:24:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2010/12/12/340380.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/340380.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2010/12/12/340380.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/340380.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/340380.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt; "><em>题记：很长都没有学到这个时间啦，怀念大三。</em><br />

<br />
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">一、摘要</span></p>
<p class="MsoNormal" style="margin-left:18.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1;
tab-stops:list 18.0pt"><span lang="EN-US" style="mso-fareast-font-family:
&quot;Times New Roman&quot;"><span style="font-size: 10pt; ">1.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体; font-size: 10pt; ">什么是&#8220;代理&#8221;</span></p>
<p class="MsoNormal" style="margin-left:18.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1;
tab-stops:list 18.0pt"><span lang="EN-US" style="mso-fareast-font-family:
&quot;Times New Roman&quot;"><span style="font-size: 10pt; ">2.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体; font-size: 10pt; ">代理模式与适配器模式、装饰者模式的区别，适用场景</span></p>
<p class="MsoNormal" style="margin-left:18.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1;
tab-stops:list 18.0pt"><span lang="EN-US" style="mso-fareast-font-family:
&quot;Times New Roman&quot;"><span style="font-size: 10pt; ">3.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体; font-size: 10pt; ">手工代理</span></p>
<p class="MsoNormal" style="margin-left:18.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1;
tab-stops:list 18.0pt"><span lang="EN-US" style="mso-fareast-font-family:
&quot;Times New Roman&quot;"><span style="font-size: 10pt; ">4.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family: 宋体; font-size: 10pt; ">动态代理的原理</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">二、什么是&#8220;代理&#8221;</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体; font-size: 10pt; ">如：一个</span><span lang="EN-US" style="font-size: 10pt; ">CEO</span><span style="font-family: 宋体; font-size: 10pt; ">，会有一个助理，任何需要</span><span lang="EN-US" style="font-size: 10pt; ">CEO</span><span style="font-family: 宋体; font-size: 10pt; ">处理的事情，都会经过助理过滤、整理后交给</span><span lang="EN-US" style="font-size: 10pt; ">CEO</span><span style="font-family: 宋体; font-size: 10pt; ">。助理就是</span><span lang="EN-US" style="font-size: 10pt; ">CEO</span><span style="font-family: 宋体; font-size: 10pt; ">的代理。</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="mso-tab-count:1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体; font-size: 10pt; ">自己理解，代理就是为帮实际的执行者，做数据的过滤和控制，为实际执行者屏蔽掉外部其它因素的影响，专心去做应该做的事情。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">三、代理模式与适配器模式、装饰者模式的区别，适用场景</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 10pt; ">1</span><span style="font-family: 宋体; font-size: 10pt; ">、代理模式</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 10pt; ">HeadFirst </span><span style="font-family: 宋体; font-size: 10pt; ">定义：为另一个对象提供一个替身或占位符以控制对这个对象的访问。<br />
<br />
<font face="'Times New Roman'" size="4"><span style="font-size: 14px;"><img src="http://www.blogjava.net/images/blogjava_net/shijian/proxy-class-diagram.jpg" width="289" height="178" alt="" /><br />
</span></font></span></p>
<font face="'Times New Roman'" size="4">
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">如上图，代理模式的结构。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">适用的场景，如：远程访问、访问权限控制、日志记录等。<br />
<br />
</span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">装饰者模式，</span><span lang="EN-US" style="font-size: 10pt; ">IO</span><span style="font-family: 宋体; font-size: 10pt; ">类图结构如下：</span></p>
</font></span><font face="'Times New Roman'" size="4"></font><img src="http://www.blogjava.net/images/blogjava_net/shijian/io-decorator.jpg" width="567" height="225" alt="" /><br />
<br />
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">可以从</span><span lang="EN-US" style="font-size: 10pt; ">OutputStream
</span><span lang="EN-US" style="font-family:Wingdings;mso-ascii-font-family:
&quot;Times New Roman&quot;;mso-hansi-font-family:&quot;Times New Roman&quot;;mso-char-type:symbol;
mso-symbol-font-family:Wingdings"><span style="font-size: 10pt; ">&#224;</span></span><span lang="EN-US" style="font-size: 10pt; "> FileOutputStream </span><span lang="EN-US" style="font-family:Wingdings;mso-ascii-font-family:&quot;Times New Roman&quot;;
mso-hansi-font-family:&quot;Times New Roman&quot;;mso-char-type:symbol;mso-symbol-font-family:
Wingdings"><span style="font-size: 10pt; ">&#224;</span></span><span lang="EN-US" style="font-size: 10pt; "> BufferedOutputStream</span><span style="font-family: 宋体; font-size: 10pt; ">，功能依次增强，为对象增加更多的行为。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">自己理解：目的不一样，代理是为控制对被代理对象的访问；装饰者，是对被装饰者功能的增强，避免过度使用继承实现不同的功能。</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<span style="font-family: 宋体; font-size: 10pt; ">适配器模式，其区别从类图即可分辨出来，如下</span><span style="font-size:10.5pt;mso-bidi-font-size:12.0pt;font-family:&quot;Times New Roman&quot;;
mso-fareast-font-family:宋体;mso-font-kerning:1.0pt;mso-ansi-language:EN-US;
mso-fareast-language:ZH-CN;mso-bidi-language:AR-SA"> </span><span style="font-family: 宋体; font-size: 10pt; ">：<br />
<br />
<img src="http://www.blogjava.net/images/blogjava_net/shijian/adap.jpg" width="398" height="148" alt="" /><br />
<br />
<p class="MsoNormal"><span lang="EN-US" style="font-size: 10pt; ">Client</span><span style="font-family: 宋体; font-size: 10pt; ">请求</span><span lang="EN-US" style="font-size: 10pt; ">ExecuteClass</span><span style="font-family: 宋体; font-size: 10pt; ">，但</span><span lang="EN-US" style="font-size: 10pt; ">ExecuteClass</span><span style="font-family: 宋体; font-size: 10pt; ">暴露的接口不符合</span><span lang="EN-US" style="font-size: 10pt; ">client</span><span style="font-family: 宋体; font-size: 10pt; ">的要求，在双方系统都不修改的情况下，利用适配器模式解决此问题。<br />
<br />
</span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">三、手工代理<br />
<br />
<img src="http://www.blogjava.net/images/blogjava_net/shijian/manul-proxy.jpg" width="321" height="187" alt="" /><br />
<br />
<span style="font-family: 宋体; font-size: 10pt; ">场景：根据</span><span lang="EN-US" style="font-family: 'Times New Roman'; font-size: 10pt; ">id</span><span style="font-family: 宋体; font-size: 10pt; ">，获取</span><span lang="EN-US" style="font-family: 'Times New Roman'; font-size: 10pt; ">Item</span><span style="font-family: 宋体; font-size: 10pt; ">；代理检查用户的权限是否有权限查看</span><span lang="EN-US" style="font-family: 'Times New Roman'; font-size: 10pt; ">Item</span><span style="font-family: 宋体; font-size: 10pt; ">，已经记录</span><span lang="EN-US" style="font-family: 'Times New Roman'; font-size: 10pt; ">log</span><span style="font-family: 宋体; font-size: 10pt; ">日志。具体代码很容易实现。<br />
<br />
</span></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; "><span style="font-size:10.5pt;mso-bidi-font-size:
12.0pt;font-family:宋体;mso-ascii-font-family:&quot;Times New Roman&quot;;mso-hansi-font-family:
&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;mso-font-kerning:1.0pt;
mso-ansi-language:EN-US;mso-fareast-language:ZH-CN;mso-bidi-language:AR-SA">
</span></span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">四、动态代理</span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">对上面的场景，如果使用动态代理，步骤：</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 10pt; ">1. </span><span style="font-family: 宋体; font-size: 10pt; ">根据</span><span lang="EN-US" style="font-size: 10pt; ">interface</span><span style="font-family: 宋体; font-size: 10pt; ">，通过</span><span lang="EN-US" style="font-size: 10pt; ">loader</span><span style="font-family: 宋体; font-size: 10pt; ">，生成</span><span lang="EN-US" style="font-size: 10pt; ">Class</span><span style="font-family: 宋体; font-size: 10pt; ">对象</span></p>
<p class="MsoNormal"><u><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">Class</span></u><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; "> clazz = Proxy.</span><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; "><em>getProxyClass</em>(ItemService.</span><strong><span lang="EN-US" style="font-family: 'Courier New'; color: #7f0055; font-size: 10pt; ">class</span></strong><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">.getClassLoader(),
ItemService.</span><strong><span lang="EN-US" style="font-family: 'Courier New'; color: #7f0055; font-size: 10pt; ">class</span></strong><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">);</span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size: 10pt; ">2. </span><span style="font-family: 宋体; font-size: 10pt; ">通过反射，获取</span><span lang="EN-US" style="font-size: 10pt; ">Class</span><span style="font-family: 宋体; font-size: 10pt; ">对象的</span><span lang="EN-US" style="font-size: 10pt; ">Construct</span><span style="font-family: 宋体; font-size: 10pt; ">对象（注意：</span><span lang="EN-US" style="font-size: 10pt; ">Construct</span><span style="font-family: 宋体; font-size: 10pt; ">对象需要的参数类型）</span></p>
<p class="MsoNormal"><u><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">Constructor</span></u><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; "> c = </span><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; "><u>clazz.getConstructor(InvocationHandler.</u></span><strong><u><span lang="EN-US" style="font-family: 'Courier New'; color: #7f0055; font-size: 10pt; ">class</span></u></strong><u><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">)</span></u><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">3. </span><span style="font-family: 宋体; font-size: 10pt; ">调用</span><span lang="EN-US" style="font-size: 10pt; ">Construct</span><span style="font-family: 宋体; font-size: 10pt; ">对象</span> <span lang="EN-US" style="font-size: 10pt; ">newInstance()</span><span style="font-family: 宋体; font-size: 10pt; ">生成实例对象</span></p>
<span lang="EN-US" style="font-family: 'Courier New'; color: #0000c0; font-size: 10pt; ">proxy</span><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; "> = (ItemService)c.newInstance(</span><strong><span lang="EN-US" style="font-family: 'Courier New'; color: #7f0055; font-size: 10pt; ">this</span></strong><span lang="EN-US" style="font-family: 'Courier New'; color: black; font-size: 10pt; ">); //this</span><span style="font-family: 宋体; color: black; font-size: 10pt; ">是</span><span style="font-size: 10pt; color: black; "><font face="'Courier New'"><span style="font-size: 10pt; ">InvocationHandler实例</span></font></span><u><span style="font-size: 10pt; font-family: 宋体; color: black; "><br />
<strong><span style="font-weight: normal; "><br />
</span></strong></span></u></span>
<p>&nbsp;</p>
<p class="MsoNormal"><span style="font-family: 宋体; "><span style="font-size:10.5pt;mso-bidi-font-size:
12.0pt;font-family:宋体;mso-ascii-font-family:&quot;Times New Roman&quot;;mso-hansi-font-family:
&quot;Times New Roman&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;mso-font-kerning:1.0pt;
mso-ansi-language:EN-US;mso-fareast-language:ZH-CN;mso-bidi-language:AR-SA"><u><span style="font-size: 10pt; font-family: 宋体; color: black; "><strong><span style="font-weight: normal;">
</span></strong></span></u></span></span></p>
<strong>
<p class="MsoNormal"><strong><span style="font-family: 宋体; font-size: 10pt; ">思考问题：实现原理是什么</span> </strong><strong><span style="font-family: 宋体; font-size: 10pt; ">？</span><span lang="EN-US" style="text-decoration: underline; "><o:p></o:p></span></strong></p>
<br />
</strong>
<p class="MsoNormal" style="text-decoration: underline; "><strong style="mso-bidi-font-weight:normal"><span style="font-family:宋体;mso-ascii-font-family:&quot;Times New Roman&quot;;mso-hansi-font-family:
&quot;Times New Roman&quot;"><img src="http://www.blogjava.net/images/blogjava_net/shijian/auto-proxy.jpg" width="422" height="165" alt="" /><span style="font-weight: normal; "><em><span style="font-style: normal;"><strong><br />
</strong></span></em></span></span><span lang="EN-US"><o:p></o:p></span></strong></p>

<p>&nbsp;</p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">对于上面场景，实际动态生成的代理的类图。对代理的任何调用都会，</span><span lang="EN-US" style="font-size: 10pt; ">super.handle.invoke()</span><span style="font-family: 宋体; font-size: 10pt; ">，用户实现</span><span lang="EN-US" style="font-size: 10pt; ">InvocationHandler</span><span style="font-family: 宋体; font-size: 10pt; ">，覆写</span><span lang="EN-US" style="font-size: 10pt; ">invoke</span><span style="font-family: 宋体; font-size: 10pt; ">方法，实现基于方法的控制。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">从类图，也解释了为什么只能实现&#8220;接口&#8221;的动态代理，因为代理本身需要继承</span><span lang="EN-US" style="font-size: 10pt; ">Proxy</span><span style="font-family: 宋体; font-size: 10pt; ">，如果实现&#8220;类&#8221;的代理，意味着要同时继承两个类，与</span><span lang="EN-US" style="font-size: 10pt; ">Java</span><span style="font-family: 宋体; font-size: 10pt; ">不支持多继承相违背。<br />
<br />
</span></p>
<p class="MsoNormal"><span style="font-family: 宋体; font-size: 10pt; ">附代码是从网上摘抄过来的，代理的源码：<br />
<font color="#008080" size="3"><span style="font-size: 13px; "><font color="#000000" size="4"><span style="font-size: 14px;"><br />
</span></font></span></font></span></p>
<font color="#008080" size="3"><font color="#000000" size="4">
<div style="background-color: #eeeeee; font-size: 13px; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff; font-size: 10pt; ">import</span><span style="color: #000000; font-size: 10pt; ">&nbsp;java.lang.reflect.InvocationHandler;<br />
</span><span style="color: #0000ff; font-size: 10pt; ">import</span><span style="color: #000000; font-size: 10pt; ">&nbsp;java.lang.reflect.Method;<br />
</span><span style="color: #0000ff; font-size: 10pt; ">import</span><span style="color: #000000; font-size: 10pt; ">&nbsp;java.lang.reflect.Proxy;<br />
</span><span style="color: #0000ff; font-size: 10pt; ">import</span><span style="color: #000000; font-size: 10pt; ">&nbsp;java.lang.reflect.UndeclaredThrowableException;<br />
</span><span style="color: #0000ff; font-size: 10pt; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">class</span><span style="color: #000000; font-size: 10pt; ">&nbsp;$Proxy0&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">extends</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Proxy&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">implements</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Manager&nbsp;{<br />
</span><span style="color: #0000ff; font-size: 10pt; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">static</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Method&nbsp;m1;<br />
</span><span style="color: #0000ff; font-size: 10pt; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">static</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Method&nbsp;m0;<br />
</span><span style="color: #0000ff; font-size: 10pt; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">static</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Method&nbsp;m3;<br />
</span><span style="color: #0000ff; font-size: 10pt; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">static</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Method&nbsp;m2;<br />
<br />
</span><span style="color: #0000ff; font-size: 10pt; ">static</span><span style="color: #000000; font-size: 10pt; ">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">try</span><span style="color: #000000; font-size: 10pt; ">&nbsp;{<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;&nbsp;m1&nbsp;</span><span style="color: #000000; font-size: 10pt; ">=</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Class.forName(</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">java.lang.Object</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">).getMethod(</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">equals</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">new</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Class[]&nbsp;{&nbsp;Class.forName(</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">java.lang.Object</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">)&nbsp;});<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;&nbsp;m0&nbsp;</span><span style="color: #000000; font-size: 10pt; ">=</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Class.forName(</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">java.lang.Object</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">).getMethod(</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">hashCode</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">new</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Class[</span><span style="color: #000000; font-size: 10pt; ">0</span><span style="color: #000000; font-size: 10pt; ">]);<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;&nbsp;m3&nbsp;</span><span style="color: #000000; font-size: 10pt; ">=</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Class.forName(</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">com.ml.test.Manager</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">).getMethod(</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">modify</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">new</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Class[</span><span style="color: #000000; font-size: 10pt; ">0</span><span style="color: #000000; font-size: 10pt; ">]);<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;&nbsp;m2&nbsp;</span><span style="color: #000000; font-size: 10pt; ">=</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Class.forName(</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">java.lang.Object</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">).getMethod(</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">toString</span><span style="color: #000000; font-size: 10pt; ">"</span><span style="color: #000000; font-size: 10pt; ">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">new</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Class[</span><span style="color: #000000; font-size: 10pt; ">0</span><span style="color: #000000; font-size: 10pt; ">]);<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">catch</span><span style="color: #000000; font-size: 10pt; ">&nbsp;(NoSuchMethodException&nbsp;nosuchmethodexception)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">new</span><span style="color: #000000; font-size: 10pt; ">&nbsp;NoSuchMethodError(nosuchmethodexception.getMessage());<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">catch</span><span style="color: #000000; font-size: 10pt; ">&nbsp;(ClassNotFoundException&nbsp;classnotfoundexception)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">new</span><span style="color: #000000; font-size: 10pt; ">&nbsp;NoClassDefFoundError(classnotfoundexception.getMessage());<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #000000; font-size: 10pt; ">
}<br />
<br />
</span><span style="color: #0000ff; font-size: 10pt; ">public</span><span style="color: #000000; font-size: 10pt; ">&nbsp;$Proxy0(InvocationHandler&nbsp;invocationhandler)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">super</span><span style="color: #000000; font-size: 10pt; ">(invocationhandler);<br /></span><span style="color: #000000; font-size: 10pt; ">
}<br /></span><span style="color: #000000; font-size: 10pt; ">
@Override<br />
</span><span style="color: #0000ff; font-size: 10pt; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">boolean</span><span style="color: #000000; font-size: 10pt; ">&nbsp;equals(Object&nbsp;obj)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">try</span><span style="color: #000000; font-size: 10pt; ">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">return</span><span style="color: #000000; font-size: 10pt; ">&nbsp;((Boolean)&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">super</span><span style="color: #000000; font-size: 10pt; ">.h.invoke(</span><span style="color: #0000ff; font-size: 10pt; ">this</span><span style="color: #000000; font-size: 10pt; ">,&nbsp;m1,&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">new</span><span style="color: #000000; font-size: 10pt; ">&nbsp;Object[]&nbsp;{&nbsp;obj&nbsp;}))<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.booleanValue();<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">catch</span><span style="color: #000000; font-size: 10pt; ">&nbsp;(Throwable&nbsp;throwable)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">new</span><span style="color: #000000; font-size: 10pt; ">&nbsp;UndeclaredThrowableException(throwable);<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #000000; font-size: 10pt; ">
}<br /></span><span style="color: #000000; font-size: 10pt; ">
@Override<br />
</span><span style="color: #0000ff; font-size: 10pt; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">int</span><span style="color: #000000; font-size: 10pt; ">&nbsp;hashCode()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">try</span><span style="color: #000000; font-size: 10pt; ">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">return</span><span style="color: #000000; font-size: 10pt; ">&nbsp;((Integer)&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">super</span><span style="color: #000000; font-size: 10pt; ">.h.invoke(</span><span style="color: #0000ff; font-size: 10pt; ">this</span><span style="color: #000000; font-size: 10pt; ">,&nbsp;m0,&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">null</span><span style="color: #000000; font-size: 10pt; ">)).intValue();<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">catch</span><span style="color: #000000; font-size: 10pt; ">&nbsp;(Throwable&nbsp;throwable)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">throw</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 10pt; ">new</span><span style="color: #000000; font-size: 10pt; ">&nbsp;UndeclaredThrowableException(throwable);<br /></span><span style="color: #000000; font-size: 10pt; ">
&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #000000; font-size: 10pt; ">
}<br /></span><span style="color: #000000; font-size: 10pt; ">
}</span><span style="color: #000000; font-size: 12pt; "><br />
</span></div>
</font></font>
<p><br /></p><img src ="http://www.blogjava.net/shijian/aggbug/340380.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2010-12-12 02:24 <a href="http://www.blogjava.net/shijian/archive/2010/12/12/340380.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ThreadLocal小理解</title><link>http://www.blogjava.net/shijian/archive/2010/12/11/340354.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Sat, 11 Dec 2010 10:50:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2010/12/11/340354.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/340354.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2010/12/11/340354.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/340354.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/340354.html</trackback:ping><description><![CDATA[<font class="Apple-style-span" color="#0000c0" face="'Courier New'" size="2"><br style="font-family: Verdana; " />
</font><font class="Apple-style-span" size="1"><em style="font-family: Verdana; ">题记：一直对ThreadLocal疑惑,听完facebook大牛演讲后,总结点东西。</em></font><br />
<br />
<font class="Apple-style-span" size="1"><span style="font-family: Verdana; ">
一、ThreadLocal的作用，整体结构</span></font><br />
<br />
<font class="Apple-style-span" size="1"><span style="font-family: Verdana; ">
二、源代码简单分析</span></font><br />
<font class="Apple-style-span" size="1"><span style="font-family: Verdana; ">
&nbsp;&nbsp;1.set方法</span></font><br />
<font class="Apple-style-span" size="1"><span style="font-family: Verdana; ">
&nbsp;&nbsp;2.get方法</span></font><br />
<br />
<font class="Apple-style-span" size="1"><span style="font-family: Verdana; ">
三、使用场景实例 ibatis SqlMapClientImp</span></font><br />
<br />
<font class="Apple-style-span" size="1"><span style="font-family: Verdana; ">
后记：折腾半天，文章的样式也调整不好，打包上传。但愿能帮到别人。</span></font><br />
<a href="/Files/shijian/ThreadLocal.rar" style="font-size: 8pt; "><span style="font-family: Verdana; ">http://www.blogjava.net/Files/shijian/ThreadLocal.rar</span></a><font class="Apple-style-span" size="1"><span style="font-family: Verdana; ">&nbsp;[</span></font><strong style="font-size: 8pt; "><span style="color: red; font-family: Verdana; ">请用&#8220;web版式视图&#8221;阅读</span></strong><font class="Apple-style-span" size="1"><span style="font-family: Verdana; ">]<br />
</span></font><br /><br /><strong>
遗留问题：<br /></strong><br />
<p style="text-indent: -18pt; "><span style="font-size: 8pt; "><span lang="EN-US" style="font-family: Verdana; ">&nbsp; &nbsp; &nbsp; 1.Thread</span><span style="font-family: Verdana; ">的</span><span lang="EN-US" style="font-size: 10pt; color: #0000c0; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; font-family: Verdana; background-position: initial initial; background-repeat: initial initial; ">ThreadLocalMap threadLocals</span><span lang="EN-US" style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">&nbsp;属性</span><span style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">什么时候实例化</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#0000C0"> </span><span style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">？</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#0000C0"> </span><span style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">线程实例化时吗</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#0000C0"> </span><span style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">？<br />
<font face="'Courier New'"><span style="font-family: Verdana; ">答：第一次set时，会判断是否为null，若为null，初始化。</span><br />
</font></span></span><span lang="EN-US" style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin"><span style="mso-list:Ignore"><span style="font:7.0pt &quot;Times New Roman&quot;"><font color="#0000C0" face="'Courier New'" size="3"><span style="font-size: 13px;"><br />
</span></font></span><span style="font: normal normal normal 7pt/normal 'Times New Roman'; font-family: Verdana; ">2.</span></span></span><span lang="EN-US" style="font-size: 10pt; color: black; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: silver; font-family: Verdana; background-position: initial initial; background-repeat: initial initial; ">ThreadLocalMap</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; "> replaceStaleEntry(key,
value, i); </span><span style="font-size: 10pt; color: black; font-family: Verdana; ">做了什么</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;
color:black"> </span><span style="font-size: 10pt; color: black; font-family: Verdana; ">？</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;
color:black"> <br />
</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">答：全清洗</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">stale</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">对象；存放当前对象在发现的第一个</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">stale</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">位置。因为Entry是继承WeakRerfence，任何一次的垃圾收集，都会导致其引用的对象被回收。<br />
</span><span lang="EN-US" style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin"><span style="mso-list:Ignore"><span style="font:7.0pt &quot;Times New Roman&quot;"><font face="宋体" size="3"><span style="font-size: 13px;"></span></font></span></span></span><span style="font-size:10.0pt;font-family:宋体;mso-ascii-font-family:&quot;Courier New&quot;;
mso-fareast-font-family:宋体;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family:
&quot;Courier New&quot;;mso-bidi-font-family:&quot;Courier New&quot;;color:black">
</span><span style="font-size:10.0pt;
font-family:宋体;mso-ascii-font-family:&quot;Courier New&quot;;mso-fareast-font-family:
宋体;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family:&quot;Courier New&quot;;
mso-bidi-font-family:&quot;Courier New&quot;;color:black"><br />
</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">
4.与</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">Map</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">方式的一些区别</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black"> </span><span style="font-size: 10pt; color: black; font-family: Verdana; ">？<br />
</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">Map</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">策略：</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">a</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">、相同</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">hash&amp;key</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">，覆盖</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">value</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">；</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black"> <span lang="EN-US" style="font-family: Verdana; ">b</span></span><span style="font-size: 10pt; color: black; font-family: Verdana; ">、相同</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">hash</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">，</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">key</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">不同，当前元素做为单向链的第一个元素，原来第一个元素做为当前元素的下一个。<br />
</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">ThreadLocalMap策略：a相同，</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">是不存在</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">b</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">情况；以</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">ThreadLocal</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">作为</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">key</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">，</span><span lang="EN-US" style="font-size: 10pt; color: black; font-family: Verdana; ">ThreadLocal</span><span lang="EN-US" style="font-size: 10pt; color: black; "><font class="Apple-style-span" face="宋体"><span style="font-family: Verdana; ">的</span></font></span><span lang="EN-US" style="font-size: 10pt; color: #0000c0; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: yellow; font-family: Verdana; background-position: initial initial; background-repeat: initial initial; ">threadLocalHashCode由</span><span style="font-size: 10pt; color: #0000c0; "><font class="Apple-style-span" face="宋体"><span style="font-family: Verdana; ">原子AtomicInteger计算getAndAdd(0x61c88647</span></font><span class="Apple-style-span" style="color: #000000; font-size: 14px; "><span style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">)得到；在</span><span lang="EN-US" style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">Entry[]</span><span style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">数组的位置，通过</span><span lang="EN-US" style="font-size: 10pt; color: #0000c0; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: yellow; font-family: Verdana; ">threadLocalHashCode</span><span lang="EN-US" style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">
&amp; (length-1)</span><span style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">计算</span><span style="font-size: 10pt; color: #0000c0; "><font class="Apple-style-span" face="'Courier New'"><span style="font-family: Verdana; ">；对于b情况，继续查找</span></font></span></span></span><span lang="EN-US" style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">Entry[]</span><span style="font-size: 10pt; color: #0000c0; font-family: Verdana; ">数组的</span><span style="font-size: 10pt; color: #0000c0; "><span class="Apple-style-span" style="color: #000000; font-size: 14px; "><span style="font-size: 10pt; color: #0000c0; "><font class="Apple-style-span" face="'Courier New'"><span style="font-family: Verdana; ">下一个位置，是否可存放（key相同或null）；当size&gt;=threshold(len*2/3)做resize=oldLen*2.</span></font></span></span></span>&nbsp;</p>
<span style="font-family: verdana, 'courier new'; font-size: 14px; line-height: 21px; "><span><span style="font: normal normal normal 7pt/normal 'Times New Roman'; "><br />
</span><span style="font: normal normal normal 7pt/normal 'Times New Roman'; font-family: Verdana; ">
3.</span></span><span style="font-size: 10pt; color: black; font-family: Verdana; ">ThreadLocalMap&nbsp;&nbsp;getEntryAfterMiss(ThreadLocal key, int i, Entry e)</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">；<br />
</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">
答：作用，查找没有存放在</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">hash</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">计算出</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">index</span><span style="font-size: 10pt; color: black; font-family: Verdana; ">位置的元素。为什么出现此情况？见4，由ThreadLocalMap策略决定.<br />
<br />
</span></span><img src ="http://www.blogjava.net/shijian/aggbug/340354.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2010-12-11 18:50 <a href="http://www.blogjava.net/shijian/archive/2010/12/11/340354.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>玩命的cookie</title><link>http://www.blogjava.net/shijian/archive/2010/11/08/337567.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Mon, 08 Nov 2010 13:41:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2010/11/08/337567.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/337567.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2010/11/08/337567.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/337567.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/337567.html</trackback:ping><description><![CDATA[<font class="Apple-style-span" size="2"><p><span style="font-family:宋体;">题记：一个</span>cookie<span style="font-family:宋体;">，整个下午都没有找到解决的办法。</span></p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">一、遇到的问题</span></p>  <p style="text-indent:21.0pt">1. <span style="font-family:宋体;">情景：访问</span>http://list.mall.daily.taobao.net/50024400/xxx<span style="font-family:宋体;">，当前页面通过</span>ajax<span style="font-family:宋体;">请求广告，请求的域为</span>http://tmatch.simba.taobao.com/xxx<span style="font-family:宋体;">；广告引擎向页面种</span>seesion<span style="font-family:宋体;">范围的</span>cookie<span style="font-family:宋体;">名</span>_back<span style="font-family:宋体;">，用于标识翻页；</span></p>  <p>&nbsp;<span>&nbsp; &nbsp; &nbsp;2. </span><span style="font-family:宋体;">问题：</span></p>  <p style="text-indent:21.0pt"><span style="font-family:宋体;">点击当前页面的翻页，</span>IE<span style="font-family:宋体;">下广告不翻页？通过</span>firebug<span style="font-family:宋体;">与</span>httpwatch<span style="font-family:宋体;">对比，发现</span>IE<span style="font-family:宋体;">下</span>cookie&#8220;_back&#8221;<span style="font-family:宋体;">不正确。开始猜测是引擎种</span>cookie<span style="font-family:宋体;">的逻辑存在问题，但很多地方都在使用此接口，均没有问题。</span></p>  <p style="text-indent:21.0pt"><span style="font-family:宋体;">且有人的机器翻页正常，此时怀疑是浏览器设置问题？再用</span>httpwatch<span style="font-family:宋体;">观察</span>&#8220;http<span style="font-family:宋体;">请求头</span>&#8221;<span style="font-family:宋体;">，发现</span>_back<span style="font-family:宋体;">没有回传给引擎（其实</span>httpwatch<span style="font-family:宋体;">的</span>cookies<span style="font-family:宋体;">也可以观察到，如果发送</span>cookie<span style="font-family:宋体;">的话，会显示为</span>Sent<span style="font-family:宋体;">；之前只观察到</span>Received<span style="font-family:宋体;">）？</span> <span style="font-family:宋体;">确认是浏览器的问题。</span></p>  <p style="text-indent:21.0pt">3. <span style="font-family:宋体;">解决：打开</span>IE<span style="font-family:宋体;">隐私设计，通常默认设置为</span>&#8220;<span style="font-family:宋体;">中</span>&#8221;<span style="font-family:宋体;">，拒绝</span>&#8220;<span style="font-family:宋体;">没有隐私政策的第三方</span><span>cookie ...&#8221;</span><span style="font-family:宋体;">，意味着</span>_back<span style="font-family:宋体;">并没有成功写入客户端，所有请求引擎导致不能正确回传</span>_back<span style="font-family:宋体;">，翻页失败。</span></p>  <p>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family:宋体;">这么说淘宝所有的广告的翻页都是不可用的</span> <span style="font-family:宋体;">？肯定不是。问题在</span>&#8221;<span style="font-family:宋体;">第一方</span> Cookie <span style="font-family:宋体;">来自您正浏览的网站，它们可以是永久的或临时的；第三方</span> Cookie <span style="font-family:宋体;">来自您正浏览的网站上的其他网站的广告&#8221;，对于浏览器</span>&#8220;taobao.net<span style="font-family:宋体;">与</span>taobao.com&#8221;<span style="font-family:宋体;">就是不同的两个网站，所以引擎的</span>_back<span style="font-family:宋体;">是无法种在客户端。此情景是</span>daliy<span style="font-family:宋体;">环境，线上的环境访问的是</span>list.mall.daily.taobao.com,<span style="font-family:宋体;">所以不存在</span>&#8220;<span style="font-family:宋体;">第三方</span>cookie&#8221;<span style="font-family:宋体;">的概念，广告是可以正确显示。</span></p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">二、关于</span>cookie<span style="font-family:宋体;">小知识</span></p>  <p>&nbsp;</p>  <p>1.IE Cookie<span style="font-family: 宋体;">的格式</span></p>  <p><span style="font-family:宋体;">第一行</span>&#8220;<span style="font-family:宋体;">名称</span>&#8221;<span style="font-family:宋体;">，第二行</span>&#8220;<span style="font-family:宋体;">值</span>&#8221;<span style="font-family:宋体;">，第三行</span>&#8220;<span style="font-family:宋体;">所属域</span>&#8221; ...<span style="font-family:宋体;">比如</span>&#8220;.taobao.com&#8221;<span style="font-family:宋体;">存在</span>cna<span style="font-family:宋体;">，此</span>cookie<span style="font-family:宋体;">会被浏览器自动发送到任何属于此域的子域；</span>www.taobao.com\taobao.com<span style="font-family:宋体;">，后面的是根域，前一个是二级域。</span>xp<span style="font-family:宋体;">存放目录为：</span><span>C:\Documents and Settings\&lt;username&gt;\Cookies\</span><span style="font-family:宋体;">，文件命名：你的用户名</span>@<span style="font-family:宋体;">生成</span>COOKIE<span style="font-family:宋体;">的</span>domain[COOKIE<span style="font-family:宋体;">改变的次数</span>].txt</p>  <p>&nbsp;&nbsp;<span style="font-family: 宋体;">参考：</span><a href="http://blog.csdn.net/zhangxinrun/archive/2010/07/31/5779574.aspx">http://blog.csdn.net/zhangxinrun/archive/2010/07/31/5779574.aspx</a></p>  <p>&nbsp;</p>  <p>2.Js Cookie<span style="font-family: 宋体;">跨域访</span></p>  <p>&nbsp;<a href="http://blog.csdn.net/tongdoudpj/archive/2009/05/10/4166096.aspx">http://blog.csdn.net/tongdoudpj/archive/2009/05/10/4166096.aspx</a></p>  <p>&nbsp;</p>  <p>3.cookie<span style="font-family: 宋体;">与</span>session<span style="font-family:宋体;">的关系</span></p>  <p style="text-indent:21.0pt"><span style="font-family:宋体;">根本的原因：</span>http<span style="font-family:宋体;">协议的无状态性，</span>cookie<span style="font-family:宋体;">的出现就是为了解决这个问题。</span></p>  <p style="text-indent:21.0pt">session<span style="font-family:宋体;">是一种在客户端与服务器之间保持状态的解决方案。服务端存储内容，返回对应的</span>key<span style="font-family:宋体;">给客户端，当下次访问时，带上此</span>key<span style="font-family:宋体;">，实现状态的维持。</span></p>  <p style="text-indent:21.0pt">session<span style="font-family:宋体;">实现：</span></p>  <p style="margin-left:21.0pt;text-indent:21.0pt">1.<span style="font-family:宋体;">依赖</span>cookie<span style="font-family:宋体;">，</span><span>The session cookie is stored in temporary memory and is not retained after the browser is closed</span><span style="font-family:宋体;">。（实际测试：IE8，未在1描述的位置找到</span>session<span style="font-family:宋体;">级别</span>cookie<span style="font-family:宋体;">对应的文件，猜测&#8216;临时存储在浏览器内存&#8217;，当关闭浏览器时则丢失key）</span></p>  <p style="margin-left:21.0pt;text-indent:21.0pt">2.url<span style="font-family:宋体;">重写。</span>Servlet<span style="font-family:宋体;">规范定义此功能。当浏览器禁用</span>cookie<span style="font-family:宋体;">时，就算</span>session<span style="font-family:宋体;">级别的内容也不会被存储。</span>resp.encodeRedirectURL(url)<span style="font-family:宋体;">，且仅当禁用</span>cookie<span style="font-family:宋体;">时有效，重写结果如：</span><a href="http://www.demo.com/cookie.do;jsessionid=19gfy1sg740dl1whwd72lbqlhb">http://www.demo.com/cookie.do;jsessionid=19gfy1sg740dl1whwd72lbqlhb</a></p>  <p style="margin-left:21.0pt;text-indent:21.0pt"><span style="font-family:宋体;">疑问：</span>server<span style="font-family:宋体;">如何判断，是否需要重写呢？从实验现象看，判断是否收到</span>name=JSESSIONID&nbsp;<span style="font-family:宋体;">的</span>cookie<span style="font-family:宋体;">，若无，则进行</span>url<span style="font-family:宋体;">重写。</span></p>  <p><span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</span><span style="font-family:宋体;">最好的方式，翻翻</span>tomcat<span style="font-family:宋体;">、</span>jetty<span style="font-family:宋体;">的源码实现，但未找到对应的代码。</span></p>  <p style="text-indent:21.0pt"><span style="font-family:宋体;">关于</span>cookie<span style="font-family:宋体;">的详细信息参见：</span>&nbsp;<a href="http://en.wikipedia.org/wiki/HTTP_cookie">http://en.wikipedia.org/wiki/HTTP_cookie</a></p>  <p>&nbsp;</p></font>
<a href="http://blog.csdn.net/garybrother/archive/2009/01/13/3768969.aspx"></a><img src ="http://www.blogjava.net/shijian/aggbug/337567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2010-11-08 21:41 <a href="http://www.blogjava.net/shijian/archive/2010/11/08/337567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于单元测试</title><link>http://www.blogjava.net/shijian/archive/2010/11/02/336853.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Tue, 02 Nov 2010 13:31:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2010/11/02/336853.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/336853.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2010/11/02/336853.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/336853.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/336853.html</trackback:ping><description><![CDATA[<em></em><span style="font-size: 12pt; "><em></em><span style="font-size: 10pt; "><em>题记：新同学分享了&#8220;测试驱动&#8221;，第一次感觉测试驱动离自己那么近。因此开始尝试。记下自己的一小点想法。</em><br />
<br />
1.一切从测试开始<br />
&nbsp;&nbsp;不管在写复杂的代码，还是简单的代码，一切从测试开始。练习成自己编码的习惯。<br />
&nbsp;&nbsp;自己的做法只能算是&#8220;伪测试驱动&#8221;，因为还是有详细的设计，但遵循此做法，对于需求的变更、代码存在的bug，导致编码修改的时候，心里是踏实的。<br />
&nbsp;&nbsp;目前自己还不能感觉到对后期的维护会带来什么样的结果？<br />
&nbsp;&nbsp;推荐《测试驱动开始》。<br />
<br />
2.工具<br />
&nbsp;&nbsp;junit、mockito、emma<br />
<br />
&nbsp;&nbsp;junit，这是大家熟知的，学到新点：a。参数化测试 &nbsp;b。private方法测试（反射） c。runwith &amp;&nbsp;Unite，组织测试单元<br />
&nbsp;&nbsp;mockito，轻量的mock工具。测试中很麻烦的一个问题是：环境依赖，比如：web中依赖容器生成request对象。mockito很好的解决大部分问题（static类与private方法未能解决）。<br />
&nbsp;&nbsp;emma,代码覆盖率检查工具，eclipse插件。效果：红色=未测试；黄色=测试不完整，只是部分逻辑；绿色=测试完整。（注意：不能绝对的追求覆盖率，一定要记住2/8原则，将主要的精力关注主要的逻辑）。<br />
<br />
3.习惯<br />
&nbsp;&nbsp;a。代码结构，3部分：prepare（包含mock）准备数据、action执行、assert验证<br />
&nbsp;&nbsp;b。方法命名：被测试方法名$测试目的，如：run$ParameterIsNull<br />
&nbsp;&nbsp;c。测试A类，有两个方法run()和prepare()，run方法调用prepare，且prepare执行非常耗时间。想要单独测试run()方法 ？<br />
&nbsp;&nbsp; &nbsp; 答案：B extends A，复写prepare方法（等于是mock&nbsp;prepare方法），单独的测试run方法逻辑。<br />
&nbsp;&nbsp;d。持续写测试代码的习惯<br />
<br />
<br />
<br />
&nbsp;&nbsp;</span></span><br />
<img src ="http://www.blogjava.net/shijian/aggbug/336853.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2010-11-02 21:31 <a href="http://www.blogjava.net/shijian/archive/2010/11/02/336853.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.java源文件是如何被找到的？</title><link>http://www.blogjava.net/shijian/archive/2010/10/17/335338.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Sat, 16 Oct 2010 17:29:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2010/10/17/335338.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/335338.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2010/10/17/335338.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/335338.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/335338.html</trackback:ping><description><![CDATA[<p align="center" style="text-align: center; "><span style="background-color: yellow;">已迁往 http://fatmind.iteye.com</span><br /><br />
</p>
<p><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">题记：</span>.java<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">源文件是如何被找到的？</span>.class<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">字节码文件是如何被找到的？</span><span style="font-family: 宋体; "><em><strong>内容：全部借鉴《Java深度历险》</strong></em></span></p>
<p>Package<span style="font-family:
宋体;Times New Roman&quot;;Times New Roman&quot;">：命名空间的问题，隔离类之间的关系。</span></p>
<p>Import<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">：声明引入的类的路径（仅在编译时有作用，编译后的文件，类的声明已经为全路径）；好处&#8220;明晰的代码结构，分离在多个文件；帮助实现动态链接的功能&#8221;。</span></p>
<p style="margin-left:21.0pt;text-indent:-21.0pt;
tab-stops:list 21.0pt">一、<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">编译</span></p>
<p><strong><span>package
edu.nctu;</span></strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong><span>import
com.taobao.Test;</span></strong></p>
<p><strong><span>import
edu.nctu.*;</span></strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong><span>public
class C</span></strong></p>
<p><strong>{</strong></p>
<p style="text-indent:21.0pt"><strong>public void print() {</strong></p>
<p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("package
test") ;</span></strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</strong></p>
<p><strong>}</strong></p>
<p><strong>&nbsp;</strong></p>
<p><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">步骤：</span></p>
<p>1. <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">根据</span>classpath<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">建立，&#8220;类相对路径参考表&#8221;</span></p>
<p><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">如：</span>javac &#8211;cp .;d:/test/<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">，在</span>d:/<span style="font-family:
宋体;Times New Roman&quot;;Times New Roman&quot;">下执行，结果：</span>d:/<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">；</span>d:/test/<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">。</span></p>
<p>2. <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">以&#8220;类相对路径参考表&#8221;作为相对起始路径，验证能够找到所有要用的</span>package<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">。</span></p>
<p align="left" style="text-align:left;text-autospace:none"><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">根据</span>import<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">引入的</span>package<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">或全限定类名，</span><span style="font-size:10.0pt;
font-family:&quot;Lucida Console&quot;;Lucida Console&quot;;">import packagename.classname</span><span style="font-size:10.0pt;
font-family:宋体;Lucida Console&quot;;Lucida Console&quot;;Lucida Console&quot;;">，</span><span style="font-size:10.0pt;font-family:MingLiU;Times New Roman&quot;;">將</span><span style="font-size:10.0pt;font-family:&quot;Lucida Console&quot;;Lucida Console&quot;;">packagename</span><span style="font-size:10.0pt;font-family:MingLiU;Times New Roman&quot;;">之中的</span><span style="font-size:10.0pt;
font-family:&quot;Lucida Console&quot;;Lucida Console&quot;;">&#8220;.&#8221;</span><span style="font-size:10.0pt;
font-family:MingLiU;Times New Roman&quot;;">以</span><span style="font-size:10.0pt;
font-family:&quot;Lucida Console&quot;;Lucida Console&quot;;">&#8220;/&#8221;</span><span style="font-size:10.0pt;
font-family:MingLiU;Times New Roman&quot;;">取代</span><span style="font-size:10.0pt;
font-family:&quot;Lucida Console&quot;;Lucida Console&quot;;">.</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.1
</span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">若</span>com.taobao.*<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">形式，验证在</span>d:/<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">目录下是否存在</span>com/taobao/<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">目录，若不存在，依次检查</span>d:/test/<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">。</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.2
</span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">若</span>com.taobao.Test<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">形式，验证是否存在</span>com/taobao/Test<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">，与上相同。</span></p>
<p>3. <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">建立&#8220;类参考表&#8221;和&#8220;相对类参考表&#8221;</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.1
</span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">类参考表：</span>com.taobao.Test</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.2
</span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">类相对参考表：</span>com.taobao.*</p>
<p>4. <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">解析</span>class{} <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">包含的代码</span></p>
<p style="text-indent:21.0pt"><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">是否全限定类名</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.1
</span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">是，绝对路径</span> =<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">&#8220;类相对路径参考表&#8221;</span>+<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">全限定类名，查找，不存在为错误；</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.2
</span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">否，绝对路径</span> =<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">&#8220;类相对路径参考表&#8221;，查找；</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.2.1<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">是，编译</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.2.2<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">否，解析</span>package</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.2.2.1 <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">在类参考表，是否存在</span>1<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">以上的同名类，出错；否则，绝对路径</span> =<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">&#8220;类相对路径参考表&#8221;</span>+ <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">&#8220;类参考表&#8221;，正确。</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.2.2.2 <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">在类参考表找不到，绝对路径</span><span>
= </span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">&#8220;类相对路径参考表&#8221;</span>+ <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">&#8220;相对类参考表&#8221;，若存在一个以上的类，出错；否则，正确。</span></p>
<p><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">提醒：</span></p>
<p style="margin-left:18.0pt;text-indent:-18.0pt;
tab-stops:list 18.0pt"><span style="Times New Roman&quot;"><span>1.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">如果已经存在</span><strong>A .class</strong><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">文件，</span><strong>A .java</strong><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">不是必须的；<br />
</span></p>
<p style="margin-left:18.0pt;text-indent:-18.0pt;
tab-stops:list 18.0pt"><span style="Times New Roman&quot;"><span>2.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">编译器在找到源码或字节码，对会验证是否属于此</span>package<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">，但没有通过</span>make<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">机制的编译，是不会验证的；make机制，即编译器自动维护具有相互依赖关系的文件；javac命令直接编译文件，如：javac -cp d:/test com.edu.C.java，编译器角度：com.edu.C.java 是一个文件名，且没有通过make机制，所以-cp指定的路径建立的</span><span style="font-family: 宋体; ">&#8220;类相对路径参考表&#8221;也不会使用，编译器直接在当前目录下查找</span><span style="font-family: 宋体; ">com.edu.C.java，结果 ClassNotFoundException 。</span></p>
<p style="margin-left:21.0pt;text-indent:-21.0pt;
tab-stops:list 21.0pt">二、<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">运行</span></p>
<p style="margin-left:18.0pt;text-indent:-18.0pt;
tab-stops:list 18.0pt"><span style="Times New Roman&quot;">1、&nbsp;</span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">编译结束后，</span>import<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">指令已经不存在，类被替换为&#8220;全限定类名&#8221;</span></p>
<p style="margin-left:18.0pt;text-indent:-18.0pt;
tab-stops:list 18.0pt"><span style="Times New Roman&quot;">2、&nbsp;</span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">运行时类的加载，都是通过</span>classloader<span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">进行，所以必须遵循正确的&#8220;包目录&#8221;结构，不管是否直接通过命令行执行。</span></p>
<p><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">步骤：</span></p>
<p style="margin-left:18.0pt;text-indent:-18.0pt;
tab-stops:list 18.0pt"><span style="Times New Roman&quot;"><span>1.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">建立&#8220;字节码路径参考表&#8221;，根据</span>classpath</p>
<p style="margin-left:18.0pt;text-indent:-18.0pt;
tab-stops:list 18.0pt"><span style="Times New Roman&quot;"><span>2.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">绝对路径</span> = <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">&#8220;字节码路径参考表&#8221;</span>+ <span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;">全限定类名，查找；加载；找不到，报错。</span></p>
<p style="margin-left:18.0pt;text-indent:-18.0pt;
tab-stops:list 18.0pt"><span style="font-family:宋体;Times New Roman&quot;;Times New Roman&quot;"><em><strong><br />
<br />
<br />
</strong></em></span></p><img src ="http://www.blogjava.net/shijian/aggbug/335338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2010-10-17 01:29 <a href="http://www.blogjava.net/shijian/archive/2010/10/17/335338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编码的一些理解</title><link>http://www.blogjava.net/shijian/archive/2010/10/05/333775.html</link><dc:creator>石建 | Fat Mind</dc:creator><author>石建 | Fat Mind</author><pubDate>Tue, 05 Oct 2010 13:12:00 GMT</pubDate><guid>http://www.blogjava.net/shijian/archive/2010/10/05/333775.html</guid><wfw:comment>http://www.blogjava.net/shijian/comments/333775.html</wfw:comment><comments>http://www.blogjava.net/shijian/archive/2010/10/05/333775.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shijian/comments/commentRss/333775.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shijian/services/trackbacks/333775.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 已迁往 &nbsp;http://fatmind.iteye.com主要参考：1.宝宝的文章《中文化和国际化问题浅析》&nbsp;&nbsp; 2.阮一峰的网络日志&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html&nbsp...&nbsp;&nbsp;<a href='http://www.blogjava.net/shijian/archive/2010/10/05/333775.html'>阅读全文</a><img src ="http://www.blogjava.net/shijian/aggbug/333775.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shijian/" target="_blank">石建 | Fat Mind</a> 2010-10-05 21:12 <a href="http://www.blogjava.net/shijian/archive/2010/10/05/333775.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>