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

<channel>
	<title>涂0实验室 &#187; java</title>
	<atom:link href="http://www.sulong.info/archives/category/java/feed" rel="self" type="application/rss+xml" />
	<link>http://www.sulong.info</link>
	<description>一个程序员的成长之路</description>
	<lastBuildDate>Fri, 27 Aug 2010 01:54:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>静态域的作用范围</title>
		<link>http://www.sulong.info/archives/443</link>
		<comments>http://www.sulong.info/archives/443#comments</comments>
		<pubDate>Wed, 25 Aug 2010 09:35:54 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[classloader]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=443</guid>
		<description><![CDATA[静态域的作用范围是在同一个类之内，类不仅有名称上的区别，还有classloader，即类加载器的问题，同一个class文件被不同的类加载器加载后，即便它们有相同的名称，但是它们并不是同一个类。因此在不同类加载器中同名类的静态变量是不共享的。下面做一个测试，来验证它。下面的Test类有一个静态域value，两个方法分别增加value的值和打印状态。 public class Test &#123; &#160; &#160; private static int value = 1; &#160; &#160; &#160; &#160; public void increase&#40;&#41; &#123; &#160; &#160; &#160; &#160; value++; &#160; &#160; &#125; &#160; &#160; &#160; &#160; public void print&#40;&#41; &#123; &#160; &#160; &#160; &#160; System.out.println&#40;&#34;My Class Loader: &#34; &#160; &#160; &#160; &#160; &#160; &#160; + this.getClass&#40;&#41;.getClassLoader&#40;&#41; + &#160;&#34;, [...]]]></description>
			<content:encoded><![CDATA[<p>静态域的作用范围是在同一个类之内，类不仅有名称上的区别，还有classloader，即类加载器的问题，同一个class文件被不同的类加载器加载后，即便它们有相同的名称，但是它们并不是同一个类。因此在<strong>不同类加载器中同名类的静态变量是不共享的</strong>。下面做一个测试，来验证它。下面的Test类有一个静态域value，两个方法分别增加value的值和打印状态。</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Test <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">int</span> value <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> increase<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; value<span style="color: #339933;">++;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> print<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;My Class Loader: &quot;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">+</span> <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">getClass</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getClassLoader</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> &nbsp;<span style="color: #0000ff;">&quot;, Value: &quot;</span> <span style="color: #339933;">+</span> value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>下面的类StaticTest，运行时创建两个类加载器，分别载入同一个class文件，并通过反射依次调用print, increase,print方法。如果静态域在整个JVM内共享，那么value被加了两次，最后会输出3；否则应该输出2。由于类加载器会先向父类加载器请求类，找不到的时候才会自己加载，所以在运行这个测试时，一定不要把Test类先放到classpath中。</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.lang.reflect.Method</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.net.URL</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.net.URLClassLoader</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> StaticTest <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> main<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> args<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Exception</span></a> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aurl+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">URL</span></a><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> classURLs <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aurl+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">URL</span></a><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aurl+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">URL</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;file:/home/sulong/tmp/&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aurlclassloader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">URLClassLoader</span></a> classLoader1 <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aurlclassloader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">URLClassLoader</span></a><span style="color: #009900;">&#40;</span>classURLs<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aurlclassloader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">URLClassLoader</span></a> classLoader2 <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aurlclassloader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">URLClassLoader</span></a><span style="color: #009900;">&#40;</span>classURLs<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; test<span style="color: #009900;">&#40;</span>classLoader1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;--------------------&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; test<span style="color: #009900;">&#40;</span>classLoader2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> test<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aclassloader+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">ClassLoader</span></a> loader<span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throws</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Exception</span></a> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">Class</span> clazz <span style="color: #339933;">=</span> loader.<span style="color: #006633;">loadClass</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Test&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Object</span></a> testObj <span style="color: #339933;">=</span> clazz.<span style="color: #006633;">newInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; invoke<span style="color: #009900;">&#40;</span>clazz, testObj, <span style="color: #0000ff;">&quot;print&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; invoke<span style="color: #009900;">&#40;</span>clazz, testObj, <span style="color: #0000ff;">&quot;increase&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; invoke<span style="color: #009900;">&#40;</span>clazz, testObj, <span style="color: #0000ff;">&quot;print&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> invoke<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">Class</span> clazz, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Object</span></a> obj, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name<span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">throws</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Exception</span></a> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Amethod+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Method</span></a> method1 <span style="color: #339933;">=</span> clazz.<span style="color: #006633;">getMethod</span><span style="color: #009900;">&#40;</span>name, <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #000000; font-weight: bold;">Class</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; method1.<span style="color: #006633;">invoke</span><span style="color: #009900;">&#40;</span>obj, <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Object</span></a><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>下面是我的机器上运行时的测试结果：</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">My Class Loader: java.net.URLClassLoader@7987aeca, Value: 1<br />
My Class Loader: java.net.URLClassLoader@7987aeca, Value: 2<br />
--------------------<br />
My Class Loader: java.net.URLClassLoader@5d0385c1, Value: 1<br />
My Class Loader: java.net.URLClassLoader@5d0385c1, Value: 2</div></div>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/443/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在Tomcat的多个WAR之间共享Spring</title>
		<link>http://www.sulong.info/archives/380</link>
		<comments>http://www.sulong.info/archives/380#comments</comments>
		<pubDate>Tue, 24 Aug 2010 11:52:40 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[技巧]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[tomcat]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=380</guid>
		<description><![CDATA[由于非技术原因，公司的专门成立的支付部，招一批Java程序员，做了支付系统；又由于非技术原因，两个月内，这个部门从领导到程序员全走光了。然后这个支付系统就移交给我们这帮受苦受难的兄弟们维护了。在看他们代码的时候发现了很有趣的东西，就是在tomcat内共享Spring context。 1，实现方法 1.1 建立一个全局的jndi资源 这个全局的jndi资源代表了一个共享的spring上下文，每次通过jndi查找资源时，都返回同一个spring上下文实例。修改tomcat/conf/context.xml文件，加入以下代码： &#160; &#160; &#60;Resource auth=&#34;Container&#34; &#160; &#160; &#160; &#160;contextConfigLocation=&#34;/com/test/application-context.xml&#34; &#160; &#160; &#160; &#160;factory=&#34;com.test.TomcatWebApplicationContextResourceFactory&#34; &#160; &#160; &#160; &#160;name=&#34;bean/RootApplicationContextFactory&#34; &#160; &#160; &#160; &#160;type=&#34;org.springframework.context.ApplicationContext&#34;/&#62; 上面这段配置的意思就是，当有人通过jndi名称&#8221;bean/RootApplicationContextFactory&#8221;来查找对象时，容器就新建一个TomcatWebApplicationContextResourceFactory类实例，并调用它的getObjectInstance方法来获得资源对象。这个工厂类要是想javax.naming.spi.ObjectFactory接口。代码如下： package com.test; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.RefAddr; import javax.naming.Reference; import javax.naming.spi.ObjectFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TomcatWebApplicationContextResourceFactory implements &#160; &#160; &#160; &#160; ObjectFactory &#123; [...]]]></description>
			<content:encoded><![CDATA[<p>由于非技术原因，公司的专门成立的支付部，招一批Java程序员，做了支付系统；又由于非技术原因，两个月内，这个部门从领导到程序员全走光了。然后这个支付系统就移交给我们这帮受苦受难的兄弟们维护了。在看他们代码的时候发现了很有趣的东西，就是在tomcat内共享Spring context。</p>
<h1> 1，实现方法</h1>
<h2>1.1 建立一个全局的jndi资源</h2>
<p>这个全局的jndi资源代表了一个共享的spring上下文，每次通过jndi查找资源时，都返回同一个spring上下文实例。修改tomcat/conf/context.xml文件，加入以下代码：</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Resource</span> <span style="color: #000066;">auth</span>=<span style="color: #ff0000;">&quot;Container&quot;</span> </span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">contextConfigLocation</span>=<span style="color: #ff0000;">&quot;/com/test/application-context.xml&quot;</span> </span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">factory</span>=<span style="color: #ff0000;">&quot;com.test.TomcatWebApplicationContextResourceFactory&quot;</span> </span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;bean/RootApplicationContextFactory&quot;</span> </span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;org.springframework.context.ApplicationContext&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></div></div>
<p>上面这段配置的意思就是，当有人通过jndi名称&#8221;bean/RootApplicationContextFactory&#8221;来查找对象时，容器就新建一个TomcatWebApplicationContextResourceFactory类实例，并调用它的getObjectInstance方法来获得资源对象。这个工厂类要是想javax.naming.spi.ObjectFactory接口。代码如下：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.test</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Hashtable</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.naming.Context</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.naming.Name</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.naming.RefAddr</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.naming.Reference</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.naming.spi.ObjectFactory</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.context.ApplicationContext</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.context.support.ClassPathXmlApplicationContext</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TomcatWebApplicationContextResourceFactory <span style="color: #000000; font-weight: bold;">implements</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobjectfactory+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">ObjectFactory</span></a> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> PARAM <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;contextConfigLocation&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> <span style="color: #000000; font-weight: bold;">DEFAULT</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;application-context.xml&quot;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> ApplicationContext context<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//被共享的spring上下文</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> init<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> confFile<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; context <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ClassPathXmlApplicationContext<span style="color: #009900;">&#40;</span>confFile<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Object</span></a> getObjectInstance<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aobject+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Object</span></a> obj, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aname+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Name</span></a> name, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Acontext+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Context</span></a> nameCtx,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Hashtable<span style="color: #339933;">&lt;?</span>, <span style="color: #339933;">?&gt;</span> environment<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aexception+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Exception</span></a> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">==</span> context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Customize the bean properties from our attributes</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Areference+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Reference</span></a> ref <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Areference+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Reference</span></a><span style="color: #009900;">&#41;</span> obj<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//从xml配置文件里取得contextConfigLocation元素的值</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Arefaddr+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">RefAddr</span></a> addr <span style="color: #339933;">=</span> ref.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>PARAM<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">!=</span> addr<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> value <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a><span style="color: #009900;">&#41;</span> addr.<span style="color: #006633;">getContent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; init<span style="color: #009900;">&#40;</span>value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; init<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">DEFAULT</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> context<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h2>1.2 在web应用中引用上面定义的资源</h2>
<p>修改tomcat/conf/web.xml，添加以下的内容，这样在这个tomcat下的所有的web应用就都可以访问共享的spring上下文了。</p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;resource-env-ref<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Object factory for Root applicationcontext<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;resource-env-ref-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> bean/RootApplicationContextFactory <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/resource-env-ref-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;resource-env-ref-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> org.springframework.context.ApplicationContext <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/resource-env-ref-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/resource-env-ref<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<h2>1.3 加入依赖的包</h2>
<p>从第一步可以看出，tomcat容器需要访问spring的一些类，需要初始化上下文，所以要把初始化上下文时用到的类共享给tomcat。最简单的方法是把所有相关的类和jar包复制到tomcat/lib目录。还可以修改catalina.properties实现，如下：</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">shared.loader=/usr/local/jars/*.jar</div></div>
<p>上面的代码让tomcat载入自定目录里面所有的jar文件。</p>
<h1>2 我的看法</h1>
<p>一个庞大的spring上下文是要占用很多内存的，所有应用共享一个上下文，而不是每个web应用一份，就可以节省不少的内存。但是由此却带来了部署和配置的麻烦。如果有人利用这种机制，让多个web应用通过共享spring bean来实现一些奇怪的功能，结果导致这些应用间相互耦合，那么以后想拆分开也不容易了。总体来说，我不喜欢这样方案，但是如果真的很穷很缺内存的话，这也不失一个好方法。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/380/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>异步调用</title>
		<link>http://www.sulong.info/archives/360</link>
		<comments>http://www.sulong.info/archives/360#comments</comments>
		<pubDate>Tue, 29 Jun 2010 15:28:36 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[异步]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=360</guid>
		<description><![CDATA[1 什么是异步 异步显然是和同步相对应的。同步调用，被调用者要执行完所有的代码才将执行流程交给调用者，在被调用者执行的过程中，调用者只能被动的等待；而异步，则是被调用先将执行流程转给调用者，然后自己再继续执行。如果调用者必须在得到被调用者的所有执行结果才能确定下一步该做什么的话，那么这种情况就该使用同步调用；相反，如果调用者不需要被调用者的执行结果，那么就可以使用异步。 2 怎样异步 在单线程或单进程等单一执行流程的情况下，实现不了能让被调用者个调用者并发执行的异步调用，这种情况下被调用者只能先将要执行的任务环境记录下来，带调用者执行完成后，再回头来执行之前要执行的任务，这样的方式其实算不上是异步，称之为推迟执行更贴切。 在多线程或多进程环境里，才能真正的实现异步，实现调用者和被调用者并发执行的异步调用。被调用者只要开启一个新的线程在新线程里执行任务，而立刻返回让调用者在当前线程继续执行，这样就可以实现异步调用了。 借助于ejb 3.1 , spring 3, seam这样的容器和框架，实现异步调用的方法非常简单，只需要再方法上加上指定的Annotation就可以了。使用spring 2的时候，可以注入taskExecutor，用taskExecutor.execute(Runnable r) 方法来实现异步。另外，通过JMS也可以实现异步。 3 异步有什么好处 说异步比同步调用性能好并不准确。假设 被调用方法里面要完成两个任务，分别耗时 t1和t2，从开始调用到调用返回的耗时，即响应时间，同步调用的时候，Rs = t1 + t2，异步调用的时候Ra = t1 + a1，其中a1代表为了异步调用开启新线程或新进程的耗时，如果要Ra &#60; Rs，显然要求a1 &#60; t2，可见如果异步执行的任务并不比启用异步执行耗时太多的话，异步执行也不会缩短响应时间。如果计算完成同等任务的总耗时的话，同步的时候 Ts = t1 + t2，异步的时候 Ta = t1 + a1 + t2，可见Ts &#60; Ta，此时异步没有任何好处。在要求响应时间非常短的互联网应用中，合理的采用异步可以提高响应速度，提升程序的负载能力。快速的响应用户的请求，将耗时多而用户不急于知道结果的任务交给有限的线程来执行。 然而，对于Java EE这样的环境，一个事务的边界往往是在一个线程里的，所以使用异步之后，就失去了事务的保护，异常后的数据补偿工作增加了程序的复杂性，也让程序更容易出错。一个不好的异步实现机制，往往给程序带来更多的隐患。比如，为每一个异步执行的任务都新建一个线程，很可能在并发数到一定程度的时候，由于创建过多的线程，达到性能瓶颈，甚至于导致程序崩溃。 4 什么时候用异步 首先只有调用者不需要立刻知道结果的任务才能被异步执行；其次被异步执行的任务耗时多于使用异步执行本身的时候，采用异步才值得；再次，要求响应时间短的时候采用异步才有意义。 典型的例子：用户支付订单后要立刻告知用户支付是否成功，并给用户发送邮件，通知仓库发货，告知物流送货。这种情况下，用户只要知道支付成功就行了，发送邮件等任务用户可以过会再感知到，而且发送邮件等任务很耗时，用户肯定不愿意等待完成所有一切之后才知道支付结果。这种情况下，将发送邮件等任务异步执行就很合适。 另外一个例子，A，B两个系统每隔一个小时对一次账，如果B发现账户和A系统不一样，则自动调整。尽管A不需要知道B的调整结果，但是A完全可以等待B执行，反正也没人等也没人急，而且对账频率低负载低，这种情况下就没有必要异步执行调整动作。]]></description>
			<content:encoded><![CDATA[<h1>1 什么是异步</h1>
<p>异步显然是和同步相对应的。同步调用，被调用者要执行完所有的代码才将执行流程交给调用者，在被调用者执行的过程中，调用者只能被动的等待；而异步，则是被调用先将执行流程转给调用者，然后自己再继续执行。如果调用者必须在得到被调用者的所有执行结果才能确定下一步该做什么的话，那么这种情况就该使用同步调用；相反，如果调用者不需要被调用者的执行结果，那么就可以使用异步。</p>
<h1>2 怎样异步</h1>
<p>在单线程或单进程等单一执行流程的情况下，实现不了能让被调用者个调用者并发执行的异步调用，这种情况下被调用者只能先将要执行的任务环境记录下来，带调用者执行完成后，再回头来执行之前要执行的任务，这样的方式其实算不上是异步，称之为推迟执行更贴切。</p>
<p>在多线程或多进程环境里，才能真正的实现异步，实现调用者和被调用者并发执行的异步调用。被调用者只要开启一个新的线程在新线程里执行任务，而立刻返回让调用者在当前线程继续执行，这样就可以实现异步调用了。</p>
<p>借助于ejb 3.1 , spring 3, seam这样的容器和框架，实现异步调用的方法非常简单，只需要再方法上加上指定的Annotation就可以了。使用spring 2的时候，可以注入taskExecutor，用taskExecutor.execute(Runnable r) 方法来实现异步。另外，通过JMS也可以实现异步。</p>
<h1>3 异步有什么好处</h1>
<p>说异步比同步调用性能好并不准确。假设 被调用方法里面要完成两个任务，分别耗时 t1和t2，从开始调用到调用返回的耗时，即响应时间，同步调用的时候，Rs = t1 + t2，异步调用的时候Ra = t1 + a1，其中a1代表为了异步调用开启新线程或新进程的耗时，如果要Ra &lt; Rs，显然要求a1 &lt; t2，可见如果异步执行的任务并不比启用异步执行耗时太多的话，异步执行也不会缩短响应时间。如果计算完成同等任务的总耗时的话，同步的时候 Ts = t1 + t2，异步的时候 Ta = t1 + a1 + t2，可见Ts &lt; Ta，此时异步没有任何好处。在要求响应时间非常短的互联网应用中，合理的采用异步可以提高响应速度，提升程序的负载能力。快速的响应用户的请求，将耗时多而用户不急于知道结果的任务交给有限的线程来执行。</p>
<p>然而，对于Java EE这样的环境，一个事务的边界往往是在一个线程里的，所以使用异步之后，就失去了事务的保护，异常后的数据补偿工作增加了程序的复杂性，也让程序更容易出错。一个不好的异步实现机制，往往给程序带来更多的隐患。比如，为每一个异步执行的任务都新建一个线程，很可能在并发数到一定程度的时候，由于创建过多的线程，达到性能瓶颈，甚至于导致程序崩溃。</p>
<h1>4 什么时候用异步</h1>
<p>首先只有调用者不需要立刻知道结果的任务才能被异步执行；其次被异步执行的任务耗时多于使用异步执行本身的时候，采用异步才值得；再次，要求响应时间短的时候采用异步才有意义。</p>
<p>典型的例子：用户支付订单后要立刻告知用户支付是否成功，并给用户发送邮件，通知仓库发货，告知物流送货。这种情况下，用户只要知道支付成功就行了，发送邮件等任务用户可以过会再感知到，而且发送邮件等任务很耗时，用户肯定不愿意等待完成所有一切之后才知道支付结果。这种情况下，将发送邮件等任务异步执行就很合适。</p>
<p>另外一个例子，A，B两个系统每隔一个小时对一次账，如果B发现账户和A系统不一样，则自动调整。尽管A不需要知道B的调整结果，但是A完全可以等待B执行，反正也没人等也没人急，而且对账频率低负载低，这种情况下就没有必要异步执行调整动作。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/360/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Java EE 6 之 Servlet 3.0</title>
		<link>http://www.sulong.info/archives/341</link>
		<comments>http://www.sulong.info/archives/341#comments</comments>
		<pubDate>Sat, 27 Feb 2010 13:42:20 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[java EE]]></category>
		<category><![CDATA[servlet]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=341</guid>
		<description><![CDATA[Servlet之所以没有像之前的ejb那样被受到那么多的诟病，是因为servlet的设计确实非常好。在最新的Java EE6版本里，这么多年都没有多少重大改动的Servlet终于添加了很多新的功能。下面我们一个一个来看 1. 基于annotation的配置 自从java 5增加了annotation后，现在annotation已经广范用于各种框架，确实减少了很多的编写配置文件的工作。现在终于可以不用写web.xml，只要通过WebServlet, WebFilter, WebListener这几个annotation就可以轻易的配置Servlet, filter和listener了。而且, web.xml已经是可选的了，就算没有它，也一样运行。 2. 异步请求处理 Servlet 3.0 新添加了一个类AsyncContext，可以通过ServletRequest活得。如果调用了ServletRequest的startAsync()，那么这个请求将会被异步处理，这意味着即使当前的线程执行结束，也不会给发送会响应，而是要等到AsyncContext的complete()方法被调用。通过AsyncContext，一样可以取到ServletRequest，和ServletResponse对象，这意味着即使最初Servlet执行的线程执行结束，也一样可以取到那次请求数据和返回客户端数据。 在通常的Servlet设计中，servlet容器会为每个客户端的请求分配一个线程，如果处理请求的过程中需要等待某种很慢的资源，在访问量大的时候，可能导致servlet容器的线程池耗光，从而无法响应后续的请求。有了异步处理的servlet之后，可以将这些线程解放出来，把它们放到一个队列里等待。比起线程，普通的对象还是要占用较少资源的。 3. Web Fragments Web容器加载的时候，会扫描WEB-INF/lib下的jar, 如果这个jar的有META-INF/web-fragment.xml，那这这个web-fragment.xml内的配置信息也会被使用。这个功能对做web框架很有用。很多web框架都是通过自定义自己的servlet, filter或listener实现的，现在，框架的开发者可以将默认的配置放到自己的jar里，使用者只要把jar丢到WEB-INF/lib/目录下就可以使用框架了，更加方便。通过web-fragment, 可以更容易的对一个war实现部署上的模块化。 4. 动态注册Web application组件 这个功能的意思是指，应用程序可以在运行时注册servlet, filter和listener。ServletContext里多了addFilter(), addServlet()等方法，来给用户调用。很奇怪的是，我只看到注册组件的，没有看到注销组件的，如果只能加不能减的话，那这一功能估计只能看作是通过xml配置的另一种方法。 5. 容器启动回调 如果WEB-INF/lib下有某个jar文件包含META-INF/services/javax.servlet.ServletContainerInitializer文件，且该文本文件内的类名所对应的类实现了javax.servlet.ServletContainerInitializer接口，那么这个类所实现的该接口方法会在容器启动时被调用。 这个接口方法是onStartup(java.util.Set]]></description>
			<content:encoded><![CDATA[<p>Servlet之所以没有像之前的ejb那样被受到那么多的诟病，是因为servlet的设计确实非常好。在最新的Java EE6版本里，这么多年都没有多少重大改动的Servlet终于添加了很多新的功能。下面我们一个一个来看</p>
<h3>1. 基于annotation的配置</h3>
<p>自从java 5增加了annotation后，现在annotation已经广范用于各种框架，确实减少了很多的编写配置文件的工作。现在终于可以不用写web.xml，只要通过WebServlet, WebFilter, WebListener这几个annotation就可以轻易的配置Servlet, filter和listener了。而且, web.xml已经是可选的了，就算没有它，也一样运行。</p>
<h3>2. 异步请求处理</h3>
<p>Servlet 3.0 新添加了一个类AsyncContext，可以通过ServletRequest活得。如果调用了ServletRequest的startAsync()，那么这个请求将会被异步处理，这意味着即使当前的线程执行结束，也不会给发送会响应，而是要等到AsyncContext的complete()方法被调用。通过AsyncContext，一样可以取到ServletRequest，和ServletResponse对象，这意味着即使最初Servlet执行的线程执行结束，也一样可以取到那次请求数据和返回客户端数据。</p>
<p>在通常的Servlet设计中，servlet容器会为每个客户端的请求分配一个线程，如果处理请求的过程中需要等待某种很慢的资源，在访问量大的时候，可能导致servlet容器的线程池耗光，从而无法响应后续的请求。有了异步处理的servlet之后，可以将这些线程解放出来，把它们放到一个队列里等待。比起线程，普通的对象还是要占用较少资源的。</p>
<h3>3. Web Fragments</h3>
<p>Web容器加载的时候，会扫描WEB-INF/lib下的jar, 如果这个jar的有META-INF/web-fragment.xml，那这这个web-fragment.xml内的配置信息也会被使用。这个功能对做web框架很有用。很多web框架都是通过自定义自己的servlet, filter或listener实现的，现在，框架的开发者可以将默认的配置放到自己的jar里，使用者只要把jar丢到WEB-INF/lib/目录下就可以使用框架了，更加方便。通过web-fragment, 可以更容易的对一个war实现部署上的模块化。</p>
<h3>4. 动态注册Web application组件</h3>
<p>这个功能的意思是指，应用程序可以在运行时注册servlet, filter和listener。ServletContext里多了addFilter(), addServlet()等方法，来给用户调用。很奇怪的是，我只看到注册组件的，没有看到注销组件的，如果只能加不能减的话，那这一功能估计只能看作是通过xml配置的另一种方法。</p>
<h3>5. 容器启动回调</h3>
<p>如果WEB-INF/lib下有某个jar文件包含META-INF/services/javax.servlet.ServletContainerInitializer文件，且该文本文件内的类名所对应的类实现了javax.servlet.ServletContainerInitializer接口，那么这个类所实现的该接口方法会在容器启动时被调用。 这个接口方法是onStartup(java.util.Set<java.lang.Class<?>> c, ServletContext ctx) , 其中c是一个类的集合。你必须在这个方法上使用HandlesTypes annation，这个annotation会指定一些类，而所有实现了，集成了或标注了这个些类的类会做成一个结合作为参数传给onStartup方法。说起来复杂，写起来简单：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@HandlesTypes<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>A.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> onStartup<span style="color: #009900;">&#40;</span>Set<span style="color: #339933;">&lt;</span>Class<span style="color: #339933;">&lt;?&gt;&gt;</span> c, ServletContext ctx<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #666666; font-style: italic;">//</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>对于上面的例子，c集合里的类要么实现了A，要么集成了A，要么标注了A。<br />
看来这个功能还是为了自定义框架用的。</p>
<h3>6. 自定义session cookie</h3>
<p>以前Session cookie的名字一般固定为JSESSIONID，现在通过ServletContext可以获得SessionCookieConfig对象，而该对象可以让我们自定义session cookie的名字等属性。</p>
<h3>7. multipart支持</h3>
<p>编写接受上传文件的程序更容易了，通过HttpServletRequest对象可以获得Part对象，每一个Part代表了上传的一个文件。调用Part.write(String)方法，可以很轻松的把上传的文件保存为参数指定的文件名。</p>
<h3>结论</h3>
<p>可以看出，这些更改，都无疑使Servlet编程更容易更灵活了。所以还是很期待能在项目中使用Servlet 3.0 。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/341/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用hibernate映射时遇到的问题</title>
		<link>http://www.sulong.info/archives/335</link>
		<comments>http://www.sulong.info/archives/335#comments</comments>
		<pubDate>Thu, 21 Jan 2010 09:35:37 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[hibernate]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=335</guid>
		<description><![CDATA[对象和关系型数据库之间存在着根本不同, ORM（对象/关系映射）试图把对象映射到关系型数据库的表结构上，从而简化存储对象到数据库及从数据库中恢复对象的复杂性，让操作数据库就像操作对象一样简单。Hibernate估计是众多ORM框架中最成熟的了，但是在处理类的继承关系时还是会有一些问题。 延迟加载与继承 先看如下的代码, 演示这一映射关系： @Entity @Table&#40;name = &#34;a&#34;&#41; @Inheritance&#40;strategy = InheritanceType.SINGLE_TABLE&#41; @DiscriminatorColumn&#40; &#160; &#160; &#160; &#160; name = &#34;disc&#34;, &#160; &#160; &#160; &#160; columnDefinition = &#34;varchar(4)&#34;, &#160; &#160; &#160; &#160; discriminatorType = DiscriminatorType.STRING&#41; public abstract class A &#123; &#160;@Id &#160;private int oid; &#160;private String name; &#125; @Entity @DiscriminatorValue&#40;&#34;b&#34;&#41; public class B extends A &#123; [...]]]></description>
			<content:encoded><![CDATA[<p>对象和关系型数据库之间存在着根本不同, ORM（对象/关系映射）试图把对象映射到关系型数据库的表结构上，从而简化存储对象到数据库及从数据库中恢复对象的复杂性，让操作数据库就像操作对象一样简单。Hibernate估计是众多ORM框架中最成熟的了，但是在处理类的继承关系时还是会有一些问题。</p>
<p>延迟加载与继承<br />
先看如下的代码, 演示这一映射关系：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><br />
@Inheritance<span style="color: #009900;">&#40;</span>strategy <span style="color: #339933;">=</span> InheritanceType.<span style="color: #006633;">SINGLE_TABLE</span><span style="color: #009900;">&#41;</span><br />
@DiscriminatorColumn<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;disc&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; columnDefinition <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;varchar(4)&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; discriminatorType <span style="color: #339933;">=</span> DiscriminatorType.<span style="color: #006633;">STRING</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> A <span style="color: #009900;">&#123;</span><br />
&nbsp;@Id<br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> oid<span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@DiscriminatorValue<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;b&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> B <span style="color: #000000; font-weight: bold;">extends</span> A <span style="color: #009900;">&#123;</span><br />
<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> age<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@DiscriminatorValue<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;c&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> C <span style="color: #000000; font-weight: bold;">extends</span> B <span style="color: #009900;">&#123;</span><br />
<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> sex<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;d&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> D <span style="color: #009900;">&#123;</span><br />
&nbsp; @Id<br />
&nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> oid<span style="color: #339933;">;</span><br />
&nbsp; @ManyToOne<span style="color: #009900;">&#40;</span>fetch <span style="color: #339933;">=</span> FetchType.<span style="color: #006633;">LAZY</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">private</span> A a<span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> A getA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #000000; font-weight: bold;">return</span> a<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>当查询 D类时，应为 D.a 是延迟加载的，所以没有查询过 a表，自然就不知道该记录对应的disc为什么值，也不知道A具体是哪种子类类型。但是查询出的d对象，如果 d.a != null d.a必须有值。Hibernate会生成一个A的子类，并用它的实例作为 d.a 当你真的要访问 d.a 的方法或域时，hibernate才会真正的去查询 a 表。 这其实就是hibernate实现延迟加载的原理。但在本例中，如果你执行如下代码就会遇到 ClassCastException，</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">D d <span style="color: #339933;">=</span> session.<span style="color: #006633;">load</span><span style="color: #009900;">&#40;</span>D.<span style="color: #000000; font-weight: bold;">class</span>, <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
C c <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>C<span style="color: #009900;">&#41;</span> d.<span style="color: #006633;">getA</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//即使d.getA()确实是C类型，也会ClassCastException</span></div></div>
</pre>
<p>hibernate生成的是A的子类，而不是B或C的子类，所以在类型转换的时候出错了。要解决这一问题，要么不要用延迟加载, 但是性能上面很可能出问题；要么不要用继承，向下面这样：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> A <span style="color: #009900;">&#123;</span><br />
&nbsp;@Id<br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> oid<span style="color: #339933;">;</span><br />
<br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name<span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> age<span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #000000; font-weight: bold;">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> sex<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@<a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Aentity+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Entity</span></a><br />
@Table<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;d&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> D <span style="color: #009900;">&#123;</span><br />
&nbsp; @Id<br />
&nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">int</span> oid<span style="color: #339933;">;</span><br />
&nbsp; @ManyToOne<span style="color: #009900;">&#40;</span>fetch <span style="color: #339933;">=</span> FetchType.<span style="color: #006633;">LAZY</span><span style="color: #009900;">&#41;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">private</span> A a<span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">public</span> A getA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #000000; font-weight: bold;">return</span> a<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>这样实际上是限制OO的能力；要么每次都显示的重新查询改对象，向这样：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">D d <span style="color: #339933;">=</span> session.<span style="color: #006633;">load</span><span style="color: #009900;">&#40;</span>D.<span style="color: #000000; font-weight: bold;">class</span>, <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
C c <span style="color: #339933;">=</span> session.<span style="color: #006633;">load</span><span style="color: #009900;">&#40;</span>C.<span style="color: #000000; font-weight: bold;">class</span>, d.<span style="color: #006633;">getA</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getOid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">//重新查，指明类型</span></div></div>
</pre>
<p>这样做既不方便，又不OO。</p>
<p>看来要想让hibernate的映射类保持对象的特性，还是有些困难的。很多时候，这些映射类最终就变成了只负责映射功能的数据库表对象了</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/335/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>JAXB中如何利用继承生成XML</title>
		<link>http://www.sulong.info/archives/326</link>
		<comments>http://www.sulong.info/archives/326#comments</comments>
		<pubDate>Sat, 14 Nov 2009 13:39:32 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[jaxb]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=326</guid>
		<description><![CDATA[问题 JAXB是我用过的java处理XML的方法中做方便的一个，在jaxb中如何使用类的集成关系有一个小小的需要注意的地方。看下面的两端XML。 XML 示例1： &#60;a&#62; &#160; &#160; &#60;b&#62;&#60;/b&#62; &#160; &#160; &#60;c&#62;&#60;/c&#62; &#60;a&#62; XML示例2： &#60;a&#62; &#160; &#160; &#60;b&#62;&#60;/b&#62; &#160; &#160; &#60;d&#62;&#60;/d&#62; &#60;a&#62; 这两段XML的唯一差别就在c元素与d元素。为了生成这两个XML，有几种方案。 方案一 不利用类的继承来重用代码，写两套Java代码, 如： @XmlRootElement&#40;name = a&#41; public class A &#123; &#160; &#160; B b; &#160; &#160; C c: &#125; @XmlRootElement&#40;name = a&#41; public class A2 &#123; &#160; &#160; B b; &#160; &#160; D [...]]]></description>
			<content:encoded><![CDATA[<h3>问题</h3>
<p>JAXB是我用过的java处理XML的方法中做方便的一个，在jaxb中如何使用类的集成关系有一个小小的需要注意的地方。看下面的两端XML。<br />
XML 示例1：</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;b<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/b<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;c<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/c<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>XML示例2：</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;b<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/b<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;d<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/d<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>这两段XML的唯一差别就在c元素与d元素。为了生成这两个XML，有几种方案。</p>
<h3>方案一</h3>
<p>不利用类的继承来重用代码，写两套Java代码, 如：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@XmlRootElement<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> a<span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> A <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; B b<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; C c<span style="color: #339933;">:</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
@XmlRootElement<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> a<span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> A2 <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; B b<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; D d<span style="color: #339933;">:</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> B <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> D <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>这一方案不是我们想要的，虽然可以解决问题，但是不能重用两个XML中共有的结构。</p>
<h3>方案二</h3>
<p>利用一个父类表示两个XML之间的共同的结构，用两个子类扩展这个父类，分别添加 C 和 D 元素。<br />
代码如下：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@XmlRootElement<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> A <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; B b<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> B <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> C <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> D <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
<br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> E <span style="color: #000000; font-weight: bold;">extends</span> A <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; C c<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> F <span style="color: #000000; font-weight: bold;">extends</span> A <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; D d<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>这一方案看似很直观，但是实践中却发现 E 和 F 却都只能生成 父类的 部分，如下的XML：</p>
<pre>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;b<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/b<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>即使把 @XmlRootElement(name = &#8220;a&#8221;) 移到 E 和 F类上也行不通。</p>
<h3>方案三</h3>
<p>用一个类代表共同的结构，用一个父类代表C和D元素，在用两个类代表具体化的C和D类，如：</p>
<pre>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@XmlRootEelemnt<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;a&quot;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> A <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; B b<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; @XmlElements<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @XmlElement<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;c&quot;</span>, type<span style="color: #339933;">=</span>C.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; @XmlElement<span style="color: #009900;">&#40;</span>name <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;d&quot;</span>, type<span style="color: #339933;">=</span>D.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; E e<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> B <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> E <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> C <span style="color: #000000; font-weight: bold;">extends</span> E <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> D <span style="color: #000000; font-weight: bold;">extends</span> E <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>这样做才最终达到目的。关键点就是@XmlElements的使用。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/326/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GroovyServlet的缺陷</title>
		<link>http://www.sulong.info/archives/319</link>
		<comments>http://www.sulong.info/archives/319#comments</comments>
		<pubDate>Fri, 07 Aug 2009 06:56:32 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[技巧]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=319</guid>
		<description><![CDATA[原本希望groovy能以php那种方式工作，但是现在看来不太可能。Groovy发行包里自带的TemplateServlet太弱，GroovyServlet也有致命的缺陷。 GroovyServlet使用GroovyScriptEngine(后面简称GSE)解析groovy文件，解析过程中GSE会智能的自动的到类路径中寻找被引用到的groovy类文件。如果被用作groovyServlet的文件被更新了，GSE会重新解析它，不需要重启服务器，就可以看到效果。可惜的是，如果被引用到的类路径中的其它的文件被更新了，GSE还在使用原来的文件，必须重启服务器才能看到效果，这是在是太令人失望了。据说groovy 1.7 里GSE会这方面增强，很期待呀。TemplateServlet干脆就连GSE也没有用，所以自动引用其他的groovy文件也不可能了。无论是GroovyServlet还是TemplateServlet都不能够像php那样通过include别的php文件来获得别的文件里定义的类，方法和闭包。 看开，在目前，如果不用grails，是没有什么好办法直接用groovy文件写网络程序的，只好把它编译成class文件，就像java生成的class一样来使用。很可气的是，我试用了几个IDE，eclipse, netbeans和idea，其中只有idea支持得还可以，但都是不算很好。看来groovy还有一段路要走。]]></description>
			<content:encoded><![CDATA[<p>原本希望groovy能以php那种方式工作，但是现在看来不太可能。Groovy发行包里自带的TemplateServlet太弱，GroovyServlet也有致命的缺陷。</p>
<p>GroovyServlet使用GroovyScriptEngine(后面简称GSE)解析groovy文件，解析过程中GSE会智能的自动的到类路径中寻找被引用到的groovy类文件。如果被用作groovyServlet的文件被更新了，GSE会重新解析它，不需要重启服务器，就可以看到效果。可惜的是，如果被引用到的类路径中的其它的文件被更新了，GSE还在使用原来的文件，必须重启服务器才能看到效果，这是在是太令人失望了。据说groovy 1.7 里GSE会这方面增强，很期待呀。TemplateServlet干脆就连GSE也没有用，所以自动引用其他的groovy文件也不可能了。无论是GroovyServlet还是TemplateServlet都不能够像php那样通过include别的php文件来获得别的文件里定义的类，方法和闭包。</p>
<p>看开，在目前，如果不用grails，是没有什么好办法直接用groovy文件写网络程序的，只好把它编译成class文件，就像java生成的class一样来使用。很可气的是，我试用了几个IDE，eclipse, netbeans和idea，其中只有idea支持得还可以，但都是不算很好。看来groovy还有一段路要走。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/319/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>groovy+spring全动态web开发方案</title>
		<link>http://www.sulong.info/archives/303</link>
		<comments>http://www.sulong.info/archives/303#comments</comments>
		<pubDate>Tue, 14 Jul 2009 05:02:07 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[技巧]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=303</guid>
		<description><![CDATA[为什么java开发没有php容易？，我在那篇文章了提出了三点原因，利用groovy，我们能在一定程度上做到那三点，从而加快了java web的开发。jsp本身以具有不需要重启就可以生效的能力，但是没有好用的map和动态类型的能力，用在前文 用groovyServlet和TemplateServlet快速开发网页中的方法，可以通过groovy让页面具有好用的map和动态类型的能力，但是 TemplateServlet的局限性 还是很难让我们单凭在页面里编程来构建规模稍大些的应用。引入spring，利用spring对动态语言的支持，我们可以将可重用的逻辑封装到由groovy编写的spring的bean里，这样，就可以最终实现从页面到后台全groovy的效果了，让java的web开发可以达到近似于php的易用度。 看看详细的做法。 把最新版的groovy-all.jar和spring.jar以及spring所依赖的相关包放到/WEB-INF/lib/目录下。 首先，在web.xml里配置好对groovyServlet, TemplateServlet和spring的支持 代码如下： &#160; &#60;context-param&#62; &#160; &#160; &#60;param-name&#62;contextConfigLocation&#60;/param-name&#62; &#160; &#160; &#60;param-value&#62;/WEB-INF/applicationContext.xml&#60;/param-value&#62; &#160; &#60;/context-param&#62; &#160; &#160; &#160; &#60;listener&#62; &#160; &#160; &#60;listener-class&#62;org.springframework.web.context.ContextLoaderListener&#60;/listener-class&#62; &#160; &#60;/listener&#62; &#160; &#160; &#60;servlet&#62; &#160; &#160; &#60;servlet-name&#62;groovlet&#60;/servlet-name&#62; &#160; &#160; &#60;servlet-class&#62;groovy.servlet.GroovyServlet&#60;/servlet-class&#62; &#160; &#60;/servlet&#62; &#160; &#160; &#60;servlet&#62; &#160; &#160; &#60;servlet-name&#62;gsp&#60;/servlet-name&#62; &#160; &#160; &#60;servlet-class&#62;groovy.servlet.TemplateServlet&#60;/servlet-class&#62; &#160; &#60;/servlet&#62; &#160; &#160; &#60;servlet-mapping&#62; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.sulong.info/archives/176"> 为什么java开发没有php容易？</a>，我在那篇文章了提出了三点原因，利用groovy，我们能在一定程度上做到那三点，从而加快了java web的开发。jsp本身以具有不需要重启就可以生效的能力，但是没有好用的map和动态类型的能力，用在前文 <a href="http://www.sulong.info/archives/280"> 用groovyServlet和TemplateServlet快速开发网页</a>中的方法，可以通过groovy让页面具有好用的map和动态类型的能力，但是 <a href="http://www.sulong.info/archives/299">TemplateServlet的局限性</a> 还是很难让我们单凭在页面里编程来构建规模稍大些的应用。引入spring，利用spring对动态语言的支持，我们可以将可重用的逻辑封装到由groovy编写的spring的bean里，这样，就可以最终实现从页面到后台全groovy的效果了，让java的web开发可以达到近似于php的易用度。</p>
<p>看看详细的做法。<br />
把最新版的groovy-all.jar和spring.jar以及spring所依赖的相关包放到/WEB-INF/lib/目录下。</p>
<h3>首先，在web.xml里配置好对groovyServlet, TemplateServlet和spring的支持</h3>
<p>代码如下：</p>
<pre lang="xml">
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;context-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>contextConfigLocation<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/WEB-INF/applicationContext.xml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/context-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;listener<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;listener-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.springframework.web.context.ContextLoaderListener<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/listener-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/listener<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>groovlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>groovy.servlet.GroovyServlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>gsp<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>groovy.servlet.TemplateServlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>groovlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>*.groovy<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> &nbsp;<br />
&nbsp; <br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>gsp<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>*.gsp<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<h3>然后，配置用groovy写spring的bean</h3>
<p>如果你要写一个id为foo的bean, 那么要先用java写一个接口，然后用groovy写Bean实现接口，这样不但可以让你以后可以更容易用java重写groovy的bean，也可以避免和spring aop的冲突。</p>
<p>interface Foo.java 代码：</p>
<pre lang="java">
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> Foo <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> shout<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>groovy实现类 FooImpl.groovy代码:</p>
<pre lang="groovy">
<div class="codecolorer-container groovy default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="groovy codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20public"><span style="color: #000000; font-weight: bold;">public</span></a> <a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20class"><span style="color: #000000; font-weight: bold;">class</span></a> FooImpl <a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20implements"><span style="color: #000000; font-weight: bold;">implements</span></a> Foo <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> sampleProp<br />
&nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20public"><span style="color: #000000; font-weight: bold;">public</span></a> <a href="http://www.google.de/search?as_q=String&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1%2E5%2E0%2Fdocs%2Fapi%2F"><span style="color: #aaaadd; font-weight: bold;">String</span></a> shout<span style="color: #66cc66;">&#40;</span><a href="http://www.google.de/search?as_q=String&amp;num=100&amp;hl=en&amp;as_occt=url&amp;as_sitesearch=java.sun.com%2Fj2se%2F1%2E5%2E0%2Fdocs%2Fapi%2F"><span style="color: #aaaadd; font-weight: bold;">String</span></a> name<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20def"><span style="color: #000000; font-weight: bold;">def</span></a> c <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #ff0000;">&quot;Groovy : ${sampleProp} ${it}&quot;</span><span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.de/search?q=site%3Adocs.codehaus.org/%20return"><span style="color: #000000; font-weight: bold;">return</span></a> c<span style="color: #66cc66;">&#40;</span>name<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span></div></div>
</pre>
<p>然后在applicationContext中配置</p>
<pre lang="xml">
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;lang:groovy</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;foo&quot;</span> <span style="color: #000066;">refresh-check-delay</span>=<span style="color: #ff0000;">&quot;5000&quot;</span> <span style="color: #000066;">script-source</span>=<span style="color: #ff0000;">&quot;classpath:FooImpl.groovy&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;lang:property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;sampleProp&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;Hello&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/lang:groovy<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>注意上面的refresh-check-delay=&#8221;5000&#8243;是让spring每过五秒钟就刷新一下groovy代码，重新编译，当最终部署的时候，可以把它去掉，这样就不会重复刷新了。但是在开发时，我们因此获得了不重启就生效能里。</p>
<h3>最后，可以在页面groovy文件中使用这个bean了</h3>
<p>使用这个bean和使用其他的spring bean没有什么区别。</p>
<pre lang="java">
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.web.context.support.WebApplicationContextUtils</span><span style="color: #339933;">;</span><br />
<br />
def spring <span style="color: #339933;">=</span> WebApplicationContextUtils.<span style="color: #006633;">getWebApplicationContext</span><span style="color: #009900;">&#40;</span>context<span style="color: #009900;">&#41;</span><br />
Foo foo <span style="color: #339933;">=</span> spring.<span style="color: #006633;">getBean</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;foo&quot;</span><span style="color: #009900;">&#41;</span><br />
foo.<span style="color: #006633;">shout</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;sulong&quot;</span><span style="color: #009900;">&#41;</span></div></div>
</pre>
<p>只要不修改applicationConfig.xml，修改其他的部分都不需要重启或重新部署，这样，你可以通过groovy和spring来达到类似于php那种快速开发的目的。并且在后期，如果有必要，你还可以通过用java重写的bean的方式，来做性能优化。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/303/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TemplateServlet的局限性</title>
		<link>http://www.sulong.info/archives/299</link>
		<comments>http://www.sulong.info/archives/299#comments</comments>
		<pubDate>Fri, 10 Jul 2009 09:38:09 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[groovy]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=299</guid>
		<description><![CDATA[我想利用TemplateServlet，像使用php那样使用groovy。只要设置好了，就可以在web目录下写gsp文件，就像写php那样，即时写即时看到效果。 但是我错了，目前的TemplateServlet非常简陋，远不能达到要求。问题主要发生在include功能。php的inclue require等功能，可以把页面变成方法库，或类库，但是在TemplateServlet的gsp里不行。我无法访问被包含的页面里的方法，闭包等。想想也很自然，每个gsp文件都有自己的名称空间。 另外，不能在gsp里定义类，这个太伤了～～～ 如果能解决以上两个问题，TemplateServlet就可以让groovy像php那样使用了。唉，那些做grails的家伙真的应该先把这块搞好，再搞重量级的东西，毕竟不是所有人都想用spring　hibernate的。 看了看gails的roadmap，今年9月的1.2版本里将有standalone gsp module，那是真正的gsp，而不是现在的简单的TemplateServlet。Grails里的gsp支持页面片段和非常方便的自定义标签，前者便于共享页面展示，后者便于共享页面行为，那么处理页面的是什么呢？还要写controller吗？到时候看吧，还是很令人期待的。]]></description>
			<content:encoded><![CDATA[<p>我想利用TemplateServlet，像使用php那样使用groovy。只要设置好了，就可以在web目录下写gsp文件，就像写php那样，即时写即时看到效果。</p>
<p>但是我错了，目前的TemplateServlet非常简陋，远不能达到要求。问题主要发生在include功能。php的inclue require等功能，可以把页面变成方法库，或类库，但是在TemplateServlet的gsp里不行。我无法访问被包含的页面里的方法，闭包等。想想也很自然，每个gsp文件都有自己的名称空间。</p>
<p>另外，不能在gsp里定义类，这个太伤了～～～</p>
<p>如果能解决以上两个问题，TemplateServlet就可以让groovy像php那样使用了。唉，那些做grails的家伙真的应该先把这块搞好，再搞重量级的东西，毕竟不是所有人都想用spring　hibernate的。</p>
<p>看了看gails的roadmap，今年9月的1.2版本里将有standalone gsp module，那是真正的gsp，而不是现在的简单的TemplateServlet。Grails里的gsp支持页面片段和非常方便的自定义标签，前者便于共享页面展示，后者便于共享页面行为，那么处理页面的是什么呢？还要写controller吗？到时候看吧，还是很令人期待的。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/299/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>浅谈TOMCAT集群</title>
		<link>http://www.sulong.info/archives/216</link>
		<comments>http://www.sulong.info/archives/216#comments</comments>
		<pubDate>Sat, 27 Jun 2009 05:26:57 +0000</pubDate>
		<dc:creator>wuwei</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[思考]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=216</guid>
		<description><![CDATA[老实说，一开始我也认为没这个必要，因为加大JVM内存就就可以了嘛，干啥要集群很多TOMCAT呢？其实不是这样的。 首先TOMCAT集群需要APACHE和TOCMAT组合在一起。APACHE作为服务端的访问入口，自动地根据TOMCAT的并发数量分配到不同的TOMCAT里。二者缺一不可。并且配置是比较麻烦的。 很多人没用到集群是因为并发数还没达到一定的程度。一般企业应用最多也就50个并发，架一个TOCMAT，内存开大点就够了。但游戏就不一样了，动不动就几百甚至1000多的并发量，一个TOMCAT吃得消吗？吃不消！通过我们的实践证明，一个TOMCAT最多支撑起150个并发数，有次我们将其开发200个，结果到了170左右TOMCAT立马崩溃。所以后来为了支撑起1000都个并发量，我们架了9个TOMCAT集群。150*9=1350，基本能满足最大的用户访问量了。 有人说还不够，加大TOMCAT的内存嘛！这么并发量不就更大了？非也！我们通过实践证明，一个TOMCAT内存到了1G以上，就起不了多大的效果了，也就是说，1G内存的TOMCAT和2G内存的TOMCAT，基本性能是一样的！哈哈 还有一点，TOMCAT是免费的哦！不花钱还能架起这么大的一个应用，够省了吧？呵呵]]></description>
			<content:encoded><![CDATA[<p>老实说，一开始我也认为没这个必要，因为加大JVM内存就就可以了嘛，干啥要集群很多TOMCAT呢？其实不是这样的。</p>
<p>首先TOMCAT集群需要APACHE和TOCMAT组合在一起。APACHE作为服务端的访问入口，自动地根据TOMCAT的并发数量分配到不同的TOMCAT里。二者缺一不可。并且配置是比较麻烦的。</p>
<p>很多人没用到集群是因为并发数还没达到一定的程度。一般企业应用最多也就50个并发，架一个TOCMAT，内存开大点就够了。但游戏就不一样了，动不动就几百甚至1000多的并发量，一个TOMCAT吃得消吗？吃不消！通过我们的实践证明，一个TOMCAT最多支撑起150个并发数，有次我们将其开发200个，结果到了170左右TOMCAT立马崩溃。所以后来为了支撑起1000都个并发量，我们架了9个TOMCAT集群。150*9=1350，基本能满足最大的用户访问量了。</p>
<p>有人说还不够，加大TOMCAT的内存嘛！这么并发量不就更大了？非也！我们通过实践证明，一个TOMCAT内存到了1G以上，就起不了多大的效果了，也就是说，1G内存的TOMCAT和2G内存的TOMCAT，基本性能是一样的！哈哈</p>
<p>还有一点，TOMCAT是免费的哦！不花钱还能架起这么大的一个应用，够省了吧？呵呵</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/216/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>ActiveMQ使用经验</title>
		<link>http://www.sulong.info/archives/207</link>
		<comments>http://www.sulong.info/archives/207#comments</comments>
		<pubDate>Thu, 18 Jun 2009 09:56:41 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[jms]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=207</guid>
		<description><![CDATA[ActiveMQ是apache的一个开源JMS服务器，不仅具备标准JMS的功能，还有很多额外的功能。公司里引入ActiveMQ后，ActiveMQ成里我们公司业务系统中最重要的一个环节。所有应用都通过jms集成，如果ActiveMQ出了故障，整个系统就瘫痪了。因此，头对ActiveMQ的性能，可靠性，以及如何正确使用，是非常的关心的，而我就被指派来做关于ActiveMQ的调研，本文对此做了些总结。 1 使用jms需要注意的问题 一下所述的问题，不仅是对ActiveMQ，对于其他的JMS也一样有效。 1.1 不要频繁的建立和关闭连接 JMS使用长连接方式，一个程序，只要和JMS服务器保持一个连接就可以了，不要频繁的建立和关闭连接。频繁的建立和关闭连接，对程序的性能影响还是很大的。这一点和jdbc还是不太一样的。 1.2 Connection的start()和stop()方法代价很高 JMS的Connection的start()和stop()方法代价很高，不能经常调用。我们试用的时候，写了个jms的connection pool，每次将connection取出pool时调用start()方法，归还时调用stop()方法，然而后来用jprofiler发现，一般的cpu时间都耗在了这两个方法上。 1.3 start()后才能收消息 Connection的start()方法调用后，才能收到jms消息。如果不调用这个方法，能发出消息，但是一直收不到消息。不知道其它的jms服务器也是这样。 1.4 显示关闭Session 如果忘记了最后关闭Connection或Session对象，都会导致内存泄漏。这个在我测试的时候也发现了。本来以为关闭了Connection，由这个Connection生成的Session也会被自动关闭，结果并非如此，Session并没有关闭，导致内存泄漏。所以一定要显示的关闭Connection和Session。 1.5 对Session做对象池 对Session做对象池，而不是Connection。Session也是昂贵的对象，每次使用都新建和关闭，代价也非常高。而且后来我们发现，原来Connection是线程安全的，而Session不是，所以后来改成了对Session做对象池，而只保留一个Connection。 2 集群 ActiveMQ有强大而灵活的集群功能，但是使用起来还是会有很多陷阱。 2.1 broker cluster和 master-slave ActiveMQ可以做broker的集群，也可以做master-slave方式的集群。前者能在多个broker之前fail-over和load-balance，但是在某个节点出故障时，可能导致消息丢失；而后者能实时备份消息，和fail-over，但是不能load-balance。broker cluser的方式，在一个broker上发送的消息可以在其它的broker上收到。当一个broker失效时，客户端可以自动的转到别的broker上运行，多个broker可以同时提供服务，但是消息只存储在一个broker上，如果那个broker失效了，那么客户端直到它重新启动后才能收到该broker上的消息，假如很不幸，那个broker的存储介质坏了，那么消息就丢失掉了。 Master-slave方式中，只有master提供服务，slave只是实时的备份master的数据，所以消息不会丢失。当master失效时，slave会自动升为master，客户端会自动转到slave上工作，所以能fail-over。由于只有master提供服务，所以不能将负载分到多个broker上。 其实单个broker的性能已经是相当的惊人了，在我们公司的机器上能达到每秒收发4000个消息，没个消息4K字节这样的速度，足够公司目前的需要了，而公司并不希望丢失任何数据，所以我们选择使用master-slave模式。 2.2 多种master-slave模式 master-slave也有多种实现方式。它们的不同只是在共享数据和锁机制上。 2.2.1 Pure master-slave Pure master-slave，显示的在配置文件中指定一个broker做为另一个broker的slave。运行时，slave同过网络自动从master出复制数据，同时在和master失去连接时自动升级为master。当master失效，slave成为master后，如果要让原先的master重新投入运行，需要停掉运行中的slave(现在升级为master了)，手动复制slave中的数据到master中。再重新启动master和slave。这种方式最简单，效率也不错，但是只能有两台做集群，只能fail-over一次，而且需要停机回复master-slave结构。 2.2.2 JDBC master-slave 这种方式不需要特殊的配置，只要让所有的节点都把数据存储到同一个数据库中。先拿到数据库表的锁的节点成为master，一旦它失效了，其它的节点获得锁，就可以成为master。因为数据通过数据库共享，放在一个地方，不需要停机恢复master-slave。这种方式，需要额外的数据库服务器，如果数据库失效了，那么就全失效了，而且速度不是很快。我们在用mysql测试时，并没有成功，master失效后，其他的节点始终没有升级成slave，可能是数据库配置的问题。 2.2.3 Share file master-slave 这种方式类似于前者，也不需要特别的配置，只是通过共享文件系统来共享数据，靠文件锁实现只有一台成为master。共享文件系统的方式有很多，我们测试了nfs v4 (v3有bug，不行)， 最终在稳定性，效率等方面不是很满意，可能是通过网络太慢了。 测试过众多master-slave模式后发现，pure方式管理起来麻烦，jdbc方式成本高，效率低，share file方式需要高性能的共享文件，都有缺点。鉴于单台activeMQ很可靠，而我们的基础平台组愿意用硬件备份，最终还是决定不用master-slave了，也不用broker cluster，就用单台，通过硬件冗余保证数据不会丢失，并找另外一台刀片机做冷备，在主服务器失效时顶替。]]></description>
			<content:encoded><![CDATA[<p>ActiveMQ是apache的一个开源JMS服务器，不仅具备标准JMS的功能，还有很多额外的功能。公司里引入ActiveMQ后，ActiveMQ成里我们公司业务系统中最重要的一个环节。所有应用都通过jms集成，如果ActiveMQ出了故障，整个系统就瘫痪了。因此，头对ActiveMQ的性能，可靠性，以及如何正确使用，是非常的关心的，而我就被指派来做关于ActiveMQ的调研，本文对此做了些总结。</p>
<h2>1 使用jms需要注意的问题</h2>
<p>一下所述的问题，不仅是对ActiveMQ，对于其他的JMS也一样有效。</p>
<h3>1.1 不要频繁的建立和关闭连接</h3>
<p>JMS使用长连接方式，一个程序，只要和JMS服务器保持一个连接就可以了，不要频繁的建立和关闭连接。频繁的建立和关闭连接，对程序的性能影响还是很大的。这一点和jdbc还是不太一样的。</p>
<h3>1.2 Connection的start()和stop()方法代价很高</h3>
<p>JMS的Connection的start()和stop()方法代价很高，不能经常调用。我们试用的时候，写了个jms的connection pool，每次将connection取出pool时调用start()方法，归还时调用stop()方法，然而后来用jprofiler发现，一般的cpu时间都耗在了这两个方法上。</p>
<h3>1.3 start()后才能收消息</h3>
<p>Connection的start()方法调用后，才能收到jms消息。如果不调用这个方法，能发出消息，但是一直收不到消息。不知道其它的jms服务器也是这样。</p>
<h3>1.4 显示关闭Session</h3>
<p>如果忘记了最后关闭Connection或Session对象，都会导致内存泄漏。这个在我测试的时候也发现了。本来以为关闭了Connection，由这个Connection生成的Session也会被自动关闭，结果并非如此，Session并没有关闭，导致内存泄漏。所以一定要显示的关闭Connection和Session。</p>
<h3>1.5 对Session做对象池</h3>
<p>对Session做对象池，而不是Connection。Session也是昂贵的对象，每次使用都新建和关闭，代价也非常高。而且后来我们发现，原来Connection是线程安全的，而Session不是，所以后来改成了对Session做对象池，而只保留一个Connection。</p>
<h2>2 集群</h2>
<p>ActiveMQ有强大而灵活的集群功能，但是使用起来还是会有很多陷阱。</p>
<h3>2.1 broker cluster和 master-slave</h3>
<p>ActiveMQ可以做broker的集群，也可以做master-slave方式的集群。前者能在多个broker之前fail-over和load-balance，但是在某个节点出故障时，可能导致消息丢失；而后者能实时备份消息，和fail-over，但是不能load-balance。broker cluser的方式，在一个broker上发送的消息可以在其它的broker上收到。当一个broker失效时，客户端可以自动的转到别的broker上运行，多个broker可以同时提供服务，但是消息只存储在一个broker上，如果那个broker失效了，那么客户端直到它重新启动后才能收到该broker上的消息，假如很不幸，那个broker的存储介质坏了，那么消息就丢失掉了。<br />
Master-slave方式中，只有master提供服务，slave只是实时的备份master的数据，所以消息不会丢失。当master失效时，slave会自动升为master，客户端会自动转到slave上工作，所以能fail-over。由于只有master提供服务，所以不能将负载分到多个broker上。<br />
其实单个broker的性能已经是相当的惊人了，在我们公司的机器上能达到每秒收发4000个消息，没个消息4K字节这样的速度，足够公司目前的需要了，而公司并不希望丢失任何数据，所以我们选择使用master-slave模式。</p>
<h3>2.2 多种master-slave模式</h3>
<p>master-slave也有多种实现方式。它们的不同只是在共享数据和锁机制上。</p>
<h4>2.2.1 Pure master-slave</h4>
<p>Pure master-slave，显示的在配置文件中指定一个broker做为另一个broker的slave。运行时，slave同过网络自动从master出复制数据，同时在和master失去连接时自动升级为master。当master失效，slave成为master后，如果要让原先的master重新投入运行，需要停掉运行中的slave(现在升级为master了)，手动复制slave中的数据到master中。再重新启动master和slave。这种方式最简单，效率也不错，但是只能有两台做集群，只能fail-over一次，而且需要停机回复master-slave结构。</p>
<h4>2.2.2 JDBC master-slave</h4>
<p>这种方式不需要特殊的配置，只要让所有的节点都把数据存储到同一个数据库中。先拿到数据库表的锁的节点成为master，一旦它失效了，其它的节点获得锁，就可以成为master。因为数据通过数据库共享，放在一个地方，不需要停机恢复master-slave。这种方式，需要额外的数据库服务器，如果数据库失效了，那么就全失效了，而且速度不是很快。我们在用mysql测试时，并没有成功，master失效后，其他的节点始终没有升级成slave，可能是数据库配置的问题。</p>
<h4>2.2.3 Share file master-slave</h4>
<p>这种方式类似于前者，也不需要特别的配置，只是通过共享文件系统来共享数据，靠文件锁实现只有一台成为master。共享文件系统的方式有很多，我们测试了nfs v4 (v3有bug，不行)， 最终在稳定性，效率等方面不是很满意，可能是通过网络太慢了。</p>
<p>测试过众多master-slave模式后发现，pure方式管理起来麻烦，jdbc方式成本高，效率低，share file方式需要高性能的共享文件，都有缺点。鉴于单台activeMQ很可靠，而我们的基础平台组愿意用硬件备份，最终还是决定不用master-slave了，也不用broker cluster，就用单台，通过硬件冗余保证数据不会丢失，并找另外一台刀片机做冷备，在主服务器失效时顶替。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/207/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>我为公司制定的Java代码规范</title>
		<link>http://www.sulong.info/archives/186</link>
		<comments>http://www.sulong.info/archives/186#comments</comments>
		<pubDate>Fri, 05 Jun 2009 06:20:07 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=186</guid>
		<description><![CDATA[Java代码规范 本Java代码规范以SUN的标准Java代码规范为基础，为适应我们公司的实际需要，可能会做一些修改。本文档中没有说明的地方，请参看SUN Java标准代码规范。如果两边有冲突，以本文档为准。 1. 标识符命名规范 1.1 概述 标识符的命名力求做到统一、达意和简洁。 1.1.1 统一 统一是指，对于同一个概念，在程序中用同一种表示方法，比如对于供应商，既可以用supplier，也可以用provider，但是我们只能选定一个使用，至少在一个Java项目中保持统一。统一是作为重要的，如果对同一概念有不同的表示方法，会使代码混乱难以理解。即使不能取得好的名称，但是只要统一，阅读起来也不会太困难，因为阅读者只要理解一次。 1.1.2 达意 达意是指，标识符能准确的表达出它所代表的意义，比如： newSupplier, OrderPaymentGatewayService等；而 supplier1, service2，idtts等则不是好的命名方式。准确有两成含义，一是正确，而是丰富。如果给一个代表供应商的变量起名是 order，显然没有正确表达。同样的，supplier1, 远没有targetSupplier意义丰富。 1.1.3 简洁 简洁是指，在统一和达意的前提下，用尽量少的标识符。如果不能达意，宁愿不要简洁。比如：theOrderNameOfTheTargetSupplierWhichIsTransfered 太长， transferedTargetSupplierOrderName则较好，但是transTgtSplOrdNm就不好了。省略元音的缩写方式不要使用，我们的英语往往还没有好到看得懂奇怪的缩写。 1.1.4 骆驼法则 Java中，除了包名，静态常量等特殊情况，大部分情况下标识符使用骆驼法则，即单词之间不使用特殊符号分割，而是通过首字母大写来分割。比如: SupplierName, addNewContract，而不是 supplier_name, add_new_contract。 1.1.5 英文 vs 拼音 尽量使用通俗易懂的英文单词，如果不会可以向队友求助，实在不行则使用汉语拼音，避免拼音与英文混用。比如表示归档，用archive比较好, 用pigeonhole则不好，用guiDang尚可接受。 1.2 包名 使用小写字母如 com.xxx.settlment ，不要 com.xxx.Settlement 单词间不要用字符隔开，比如 com.xxx.settlment.jsfutil ，而不要 com.xxx.settlement.jsf_util 1.3 类名 1.3.1 首字母大写 类名要首字母大写，比如 SupplierService, PaymentOrderAction；不要 [...]]]></description>
			<content:encoded><![CDATA[<h1>Java代码规范</h1>
<p>本Java代码规范以SUN的标准Java代码规范为基础，为适应我们公司的实际需要，可能会做一些修改。本文档中没有说明的地方，请参看SUN Java标准代码规范。如果两边有冲突，以本文档为准。</p>
<h2>1. 标识符命名规范</h2>
<h3>1.1 概述</h3>
<p>标识符的命名力求做到统一、达意和简洁。</p>
<h4>1.1.1 统一</h4>
<p>统一是指，对于同一个概念，在程序中用同一种表示方法，比如对于供应商，既可以用supplier，也可以用provider，但是我们只能选定一个使用，至少在一个Java项目中保持统一。统一是作为重要的，如果对同一概念有不同的表示方法，会使代码混乱难以理解。即使不能取得好的名称，但是只要统一，阅读起来也不会太困难，因为阅读者只要理解一次。</p>
<h4>1.1.2 达意</h4>
<p>达意是指，标识符能准确的表达出它所代表的意义，比如： newSupplier, OrderPaymentGatewayService等；而 supplier1, service2，idtts等则不是好的命名方式。准确有两成含义，一是正确，而是丰富。如果给一个代表供应商的变量起名是 order，显然没有正确表达。同样的，supplier1, 远没有targetSupplier意义丰富。</p>
<h4>1.1.3 简洁</h4>
<p>简洁是指，在统一和达意的前提下，用尽量少的标识符。如果不能达意，宁愿不要简洁。比如：theOrderNameOfTheTargetSupplierWhichIsTransfered 太长， transferedTargetSupplierOrderName则较好，但是transTgtSplOrdNm就不好了。省略元音的缩写方式不要使用，我们的英语往往还没有好到看得懂奇怪的缩写。</p>
<h4>1.1.4 骆驼法则</h4>
<p>Java中，除了包名，静态常量等特殊情况，大部分情况下标识符使用骆驼法则，即单词之间不使用特殊符号分割，而是通过首字母大写来分割。比如: SupplierName, addNewContract，而不是 supplier_name, add_new_contract。</p>
<h4>1.1.5 英文 vs 拼音</h4>
<p>尽量使用通俗易懂的英文单词，如果不会可以向队友求助，实在不行则使用汉语拼音，避免拼音与英文混用。比如表示归档，用archive比较好, 用pigeonhole则不好，用guiDang尚可接受。</p>
<h3>1.2 包名</h3>
<p>使用小写字母如</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">com.<span style="color: #006633;">xxx</span>.<span style="color: #006633;">settlment</span></div></div>
<p>，不要</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">com.<span style="color: #006633;">xxx</span>.<span style="color: #006633;">Settlement</span></div></div>
<p>单词间不要用字符隔开，比如</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">com.<span style="color: #006633;">xxx</span>.<span style="color: #006633;">settlment</span>.<span style="color: #006633;">jsfutil</span></div></div>
<p>，而不要</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">com.<span style="color: #006633;">xxx</span>.<span style="color: #006633;">settlement</span>.<span style="color: #006633;">jsf_util</span></div></div>
<h3>1.3 类名</h3>
<h4>1.3.1 首字母大写</h4>
<p>类名要首字母大写，比如 SupplierService, PaymentOrderAction；不要 supplierService, paymentOrderAction.</p>
<h4>1.3.2 后缀</h4>
<p>类名往往用不同的后缀表达额外的意思，如下表：</p>
<table border="1px">
<tr>
<td>后缀名</td>
<td>意义</td>
<td>举例</td>
</tr>
<tr>
<td>Service</td>
<td>表明这个类是个服务类，里面包含了给其他类提同业务服务的方法</td>
<td>PaymentOrderService</td>
</tr>
<tr>
<td>Impl</td>
<td>这个类是一个实现类，而不是接口</td>
<td>PaymentOrderServiceImpl</td>
</tr>
<tr>
<td>Inter</td>
<td>这个类是一个接口</td>
<td>LifeCycleInter</td>
</tr>
<tr>
<td>Dao</td>
<td>这个类封装了数据访问方法</td>
<td>PaymentOrderDao</td>
</tr>
<tr>
<td>Action</td>
<td>直接处理页面请求，管理页面逻辑了类</td>
<td>UpdateOrderListAction</td>
</tr>
<tr>
<td>Listener</td>
<td>响应某种事件的类</td>
<td>	PaymentSuccessListener</td>
</tr>
<tr>
<td>Event</td>
<td>这个类代表了某种事件</td>
<td>PaymentSuccessEvent</td>
</tr>
<tr>
<td>Servlet</td>
<td>一个Servlet</td>
<td>PaymentCallbackServlet</td>
</tr>
<tr>
<td>Factory</td>
<td>生成某种对象工厂的类</td>
<td>PaymentOrderFactory</td>
</tr>
<tr>
<td>Adapter</td>
<td>用来连接某种以前不被支持的对象的类</td>
<td>DatabaseLogAdapter</td>
</tr>
<tr>
<td>Job</td>
<td>某种按时间运行的任务</td>
<td>PaymentOrderCancelJob</td>
</tr>
<tr>
<td>Wrapper</td>
<td>这是一个包装类，为了给某个类提供没有的能力</td>
<td>	SelectableOrderListWrapper</td>
</tr>
<tr>
<td>Bean</td>
<td>这是一个POJO</td>
<td>	MenuStateBean</td>
</tr>
</table>
<h3>1.4 方法名</h3>
<p>首字母小写，如 addOrder() 不要 AddOrder()<br />
动词在前，如 addOrder()，不要orderAdd()<br />
动词前缀往往表达特定的含义，如下表：</p>
<table border="1px">
<tr>
<td>前缀名</td>
<td>	意义</td>
<td>	举例</td>
</tr>
<tr>
<td>create</td>
<td>	创建</td>
<td>	createOrder()</td>
</tr>
<tr>
<td>delete</td>
<td>	删除</td>
<td>	deleteOrder()</td>
</tr>
<tr>
<td>add</td>
<td>	创建，暗示新创建的对象属于某个集合</td>
<td>	addPaidOrder()</td>
</tr>
<tr>
<td>remove</td>
<td>	删除</td>
<td>	removeOrder()</td>
</tr>
<tr>
<td>init或则initialize</td>
<td>	初始化，暗示会做些诸如获取资源等特殊动作</td>
<td>	initializeObjectPool</td>
</tr>
<tr>
<td>destroy</td>
<td>	销毁，暗示会做些诸如释放资源的特殊动作</td>
<td>	destroyObjectPool</td>
</tr>
<tr>
<td>open</td>
<td>	打开</td>
<td>	openConnection()</td>
</tr>
<tr>
<td>close</td>
<td>	关闭</td>
<td>	closeConnection()<</td>
</tr>
<tr>
<td>read</td>
<td>	读取</td>
<td>	readUserName()</td>
</tr>
<tr>
<td>write</td>
<td>	写入</td>
<td>	writeUserName()</td>
</tr>
<tr>
<td>get</td>
<td>	获得</td>
<td>	getName()</td>
</tr>
<tr>
<td>set</td>
<td>	设置</td>
<td>	setName()</td>
</tr>
<tr>
<td>prepare</td>
<td>	准备</td>
<td>	prepareOrderList()</td>
</tr>
<tr>
<td>copy</td>
<td>	复制</td>
<td>	copyCustomerList()</td>
</tr>
<tr>
<td>modity</td>
<td>	修改</td>
<td>	modifyActualTotalAmount()</td>
</tr>
<tr>
<td>calculate</td>
<td>	数值计算</td>
<td>	calculateCommission()</td>
</tr>
<tr>
<td>do	</td>
<td>执行某个过程或流程</td>
<td>	doOrderCancelJob()</td>
</tr>
<tr>
<td>dispatch</td>
<td>	判断程序流程转向</td>
<td>	dispatchUserRequest()</td>
</tr>
<tr>
<td>start</td>
<td>	开始</td>
<td>	startOrderProcessing()</td>
</tr>
<tr>
<td>stop</td>
<td>	结束</td>
<td>	stopOrderProcessing()</td>
</tr>
<tr>
<td>send</td>
<td>	发送某个消息或事件</td>
<td>	sendOrderPaidMessage()</td>
</tr>
<tr>
<td>receive</td>
<td>	接受消息或时间</td>
<td>	receiveOrderPaidMessgae()</td>
</tr>
<tr>
<td>respond</td>
<td>	响应用户动作</td>
<td>	responseOrderListItemClicked()</td>
</tr>
<tr>
<td>find</td>
<td>	查找对象</td>
<td>	findNewSupplier()</td>
</tr>
<tr>
<td>update</td>
<td>	更新对象</td>
<td>	updateCommission()</td>
</tr>
</table>
<p>find方法在业务层尽量表达业务含义，比如 findUnsettledOrders()，查询未结算订单，而不要findOrdersByStatus()。 数据访问层，find,update等方法可以表达要执行的sql，比如findByStatusAndSupplierIdOrderByName(Status.PAID, 345)</p>
<h3>1.5 域（field）名</h3>
<h4>1.5.1 静态常量</h4>
<p>全大写用下划线分割，如</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> find <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> ORDER_PAID_EVENT <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;ORDER_PAID_EVENT&quot;</span><span style="color: #339933;">;</span></div></div>
<h4>1.5.2 枚举</h4>
<p>全大写，用下划线分割，如</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">enum</span> Events <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; ORDER_PAID,<br />
&nbsp; &nbsp; ORDER_CREATED<br />
<span style="color: #009900;">&#125;</span></div></div>
<h4>1.5.3 其他<br />
<h4>
<p>首字母小写，骆驼法则，如：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> orderName<span style="color: #339933;">;</span></div></div>
<h3>1.6 局部变量名</h3>
<p>参数和局部变量名首字母小写，骆驼法则。尽量不要和域冲突，尽量表达这个变量在方法中的意义。</p>
<h2>2. 代码格式</h2>
<p>用空格字符缩进源代码，不要用tab，每个缩进4个空格。</p>
<h3>2.1 源文件编码</h3>
<p>源文件使用utf-8编码，结尾用unix n 分格。</p>
<h3>2.2 行宽</h3>
<p>行宽度不要超过130。</p>
<h3>2.3 包的导入</h3>
<p>删除不用的导入，尽量不要使用整个包的导入。在eclipse下经常使用快捷键 ctrl+shift+o 修正导入。</p>
<h3>2.4 类格式</h3>
<h3>2.5 域格式</h3>
<p>每行只能声明一个域。<br />
域的声明用空行隔开。</p>
<h3>2.5 方法格式</h3>
<h3>2.6 代码块格式</h3>
<h4>2.6.1 缩进风格</h4>
<p>大括号的开始在代码块开始的行尾，闭合在和代码块同一缩进的行首，例如：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.test</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TestStyle <span style="color: #000000; font-weight: bold;">extends</span> SomeClass <span style="color: #000000; font-weight: bold;">implements</span> AppleInter, BananaInter <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> THIS_IS_CONST <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;CONST VALUE&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> main<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">int</span> localVariable <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> compute<span style="color: #009900;">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> arg<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>arg.<span style="color: #006633;">length</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> &nbsp;<span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>arg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Asystem+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">System</span></a>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span>arg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>condition<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">do</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; otherMethod<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>condition<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">switch</span> <span style="color: #009900;">&#40;</span>i<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callFunction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callFunctionb<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">default</span><span style="color: #339933;">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h4>2.6.2 空格的使用</h4>
<h5>2.6.2.1 表示分割时用一个空格</h5>
<p>不能这样：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#40;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a <span style="color: #339933;">&gt;</span> &nbsp; &nbsp; &nbsp; &nbsp;b &nbsp; <span style="color: #009900;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//do something here</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></div>
<h5>2.6.2.2 二元三元运算符两边用一个空格隔开</h5>
<p>如下：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">a <span style="color: #339933;">+</span> b <span style="color: #339933;">=</span> c<span style="color: #339933;">;</span><br />
b <span style="color: #339933;">-</span> d <span style="color: #339933;">=</span> e<span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">return</span> a <span style="color: #339933;">==</span> b <span style="color: #339933;">?</span> <span style="color: #cc66cc;">1</span> <span style="color: #339933;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span></div></div>
<p>不能如下：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">a<span style="color: #339933;">+</span>b<span style="color: #339933;">=</span>c<span style="color: #339933;">;</span><br />
b<span style="color: #339933;">-</span>d<span style="color: #339933;">=</span>e<span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">return</span> a<span style="color: #339933;">==</span>b<span style="color: #339933;">?</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">:</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span></div></div>
<h5>2.6.2.3 逗号语句后如不还行，紧跟一个空格</h5>
<p>如下：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">call<span style="color: #009900;">&#40;</span>a, b, c<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>不能如下：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">call<span style="color: #009900;">&#40;</span>a,b,c<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<h4>2.6.3 空行的使用</h4>
<p>空行可以表达代码在语义上的分割，注释的作用范围，等等。将类似操作，或一组操作放在一起不用空行隔开，而用空行隔开不同组的代码， 如图：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">order <span style="color: #339933;">=</span> orderDao.<span style="color: #006633;">findOrderById</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//update properties</span><br />
order.<span style="color: #006633;">setUserName</span><span style="color: #009900;">&#40;</span>userName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
order.<span style="color: #006633;">setPrice</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">456</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
order.<span style="color: #006633;">setStatus</span><span style="color: #009900;">&#40;</span>PAID<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
orderService.<span style="color: #006633;">updateTotalAmount</span><span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<br />
session.<span style="color: #006633;">saveOrUpdate</span><span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>上例中的空行，使注释的作用域很明显.</p>
<ul>
<li>连续两行的空行代表更大的语义分割。</li>
<li>方法之间用空行分割</li>
<li>域之间用空行分割</li>
<li>超过十行的代码如果还不用空行分割，就会增加阅读困难</li>
</ul>
<h2>3. 注释规范</h2>
<h3>3.1 注释 vs 代码</h3>
<ul>
<li>注释宜少二精，不宜多而滥，更不能误导</li>
<li>命名达意，结构清晰， 类和方法等责任明确，往往不需要，或者只需要很少注释，就可以让人读懂；相反，代码混乱，再多的注释都不能弥补。所以，应当先在代码本身下功夫。</li>
<li>不能正确表达代码意义的注释，只会损害代码的可读性。</li>
<li>过于详细的注释，对显而易见的代码添加的注释，罗嗦的注释，还不如不写</li>
<p>。</p>
<li>注释要和代码同步，过多的注释会成为开发的负担</li>
<li>注释不是用来管理代码版本的，如果有代码不要了，直接删除，svn会有记录的，不要注释掉，否则以后没人知道那段注释掉的代码该不该删除。</li>
</ul>
<h3>3.2 Java Doc</h3>
<p>表明类、域和方法等的意义和用法等的注释，要以javadoc的方式来写。Java Doc是个类的使用者来看的，主要介绍 是什么，怎么用等信息。凡是类的使用者需要知道，都要用Java Doc 来写。非Java Doc的注释，往往是个代码的维护者看的，着重告述读者为什么这样写，如何修改，注意什么问题等。 如下：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
* This is a class comment<br />
*/</span><br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TestClass <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
&nbsp; &nbsp; * This is a field comment<br />
&nbsp; &nbsp; */</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Astring+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">String</span></a> name<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
&nbsp; &nbsp; * This is a method comment<br />
&nbsp; &nbsp; */</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> call<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h3>3.3 块级别注释</h3>
<h4>3.3.1 块级别注释，单行时用 //, 多行时用 /* .. */。</h4>
<h4>3.3.2 较短的代码块用空行表示注释作用域</h4>
<h4>3.3.3 较长的代码块要用</h4>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">/*------ start: ------*/</span><br />
和<br />
<span style="color: #666666; font-style: italic;">/*-------- end: -------*/</span></div></div>
<p>包围<br />
如：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">/*----------start: 订单处理 ------- */</span><br />
<span style="color: #666666; font-style: italic;">//取得dao</span><br />
OrderDao dao <span style="color: #339933;">=</span> Factory.<span style="color: #006633;">getDao</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;OrderDao&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">/* 查询订单 */</span><br />
Order order <span style="color: #339933;">=</span> dao.<span style="color: #006633;">findById</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">456</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//更新订单</span><br />
order.<span style="color: #006633;">setUserName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;uu&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
order.<span style="color: #006633;">setPassword</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;pass&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
order.<span style="color: #006633;">setPrice</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;ddd&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
orderDao.<span style="color: #006633;">save</span><span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #666666; font-style: italic;">/*----------end: 订单处理 ------- */</span></div></div>
<h4>3.3.4 可以考虑使用大括号来表示注释范围</h4>
<p>使用大括号表示注释作用范围的例子：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">/*----------订单处理 ------- */</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//取得dao</span><br />
&nbsp; &nbsp; OrderDao dao <span style="color: #339933;">=</span> Factory.<span style="color: #006633;">getDao</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;OrderDao&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">/* 查询订单 */</span><br />
&nbsp; &nbsp; Order order <span style="color: #339933;">=</span> dao.<span style="color: #006633;">findById</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">456</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//更新订单</span><br />
&nbsp; &nbsp; order.<span style="color: #006633;">setUserName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;uu&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; order.<span style="color: #006633;">setPassword</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;pass&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; order.<span style="color: #006633;">setPrice</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;ddd&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; orderDao.<span style="color: #006633;">save</span><span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h3>3.4 行内注释</h3>
<p>行内注释用 // 写在行尾</p>
<h2>4 最佳实践和禁忌</h2>
<h3>4.1 每次保存的时候，都让你的代码是最美的</h3>
<p>程序员都是懒惰的，不要想着等我完成了功能，再来优化代码的格式和结构，等真的把功能完成，很少有人会再愿意回头调整代码。</p>
<h3>4.2 使用log而不是System.out.println()</h3>
<p>log可以设定级别，可以控制输出到哪里，容易区分是在代码的什么地方打印的，而System.out.print则不行。而且，System.out.print的速度很慢。所以，除非是有意的，否则，都要用log。至少在提交到svn之前把System.out.print换成log。</p>
<h3>4.3 每个if while for等语句，都不要省略大括号{}</h3>
<p>看下面的代码：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;</span> b<span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; a<span style="color: #339933;">++;</span></div></div>
<p>如果在以后维护的时候，需要在a > b 时，把b++，一步小心就会写成：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;</span> b<span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; a<span style="color: #339933;">++;</span><br />
&nbsp; &nbsp; b<span style="color: #339933;">++;</span></div></div>
<p>这样就错了，因为无论a和b是什么关系，b++都会执行。 如果一开始就这样写：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;</span> b<span style="color: #009900;">&#41;</span> &nbsp;<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; a<span style="color: #339933;">++;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>相信没有哪个笨蛋会把b++添加错的。而且，这个大括号使作用范围更明显，尤其是后面那行很长要折行时。</p>
<h3>4.4 善用TODO:</h3>
<p>在代码中加入 //TODO: ，大部分的ide都会帮你提示，让你知道你还有什么事没有做。比如：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>order.<span style="color: #006633;">isPaid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//TODO: 更新订单</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h3>4.5 在需要留空的地方放一个空语句或注释，告述读者，你是故意的</h3>
<p>比如：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>exists<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>或：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>exists<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//nothing to do</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h3>4.6 不要再对boolean值做true false判断</h3>
<p>比如：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>order.<span style="color: #006633;">isPaid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Do something here</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>不如写成：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>order.<span style="color: #006633;">isPaid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//Do something here</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>后者读起来就很是 if order is paid, &#8230;. 要比 if order&#8217;s isPaid method returns true, … 更容易理解</p>
<h3>4.7 减少代码嵌套层次</h3>
<p>代码嵌套层次达3层以上时，一般人理解起来都会困难。下面的代码是一个简单的例子：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> demo<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> a, <span style="color: #000066; font-weight: bold;">int</span> b, <span style="color: #000066; font-weight: bold;">int</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>b <span style="color: #339933;">&gt;</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; doJobA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>b <span style="color: #339933;">&lt;</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; doJobB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>b <span style="color: #339933;">&gt;</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&lt;</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; doJobC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <br />
<span style="color: #009900;">&#125;</span></div></div>
<p>减少嵌套的方法有很多：</p>
<ul>
<li>合并条件</li>
<li>利用 return 以省略后面的else</li>
<li>利用子方法</li>
</ul>
<p>比如上例，合并条件后成为：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> demo<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> a, <span style="color: #000066; font-weight: bold;">int</span> b, <span style="color: #000066; font-weight: bold;">int</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;</span> b <span style="color: #339933;">&amp;&amp;</span> b <span style="color: #339933;">&gt;</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doJobA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;</span> b <span style="color: #339933;">&amp;&amp;</span> c <span style="color: #339933;">&gt;</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doJobB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&lt;=</span> b <span style="color: #339933;">&amp;&amp;</span> c <span style="color: #339933;">&lt;</span> b <span style="color: #339933;">&amp;&amp;</span> a <span style="color: #339933;">&lt;</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doJobC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>如果利用return 则成为：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> demo<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> a, <span style="color: #000066; font-weight: bold;">int</span> b, <span style="color: #000066; font-weight: bold;">int</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;</span> b<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>b <span style="color: #339933;">&gt;</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; doJobA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doJobB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>b <span style="color: #339933;">&gt;</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&lt;</span> c<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; doJobC<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <br />
<span style="color: #009900;">&#125;</span></div></div>
<p>利用子方法，就是将嵌套的程序提取出来放到另外的方法里。</p>
<h3>4.8 程序职责单一</h3>
<p>关注点分离是软件开发的真理。人类自所以能够完成复杂的工作，就是因为人类能够将工作分解到较小级别的任务上，在做每个任务时关注更少的东西。让程序单元的职责单一，可以使你在编写这段程序时关注更少的东西，从而降低难度，减少出错。</p>
<h3>4.9 变量的声明，初始化和被使用尽量放到一起</h3>
<p>比方说如下代码：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066; font-weight: bold;">int</span> orderNum<span style="color: #339933;">=</span> getOrderNum<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//do something withou orderNum here</span><br />
<br />
call<span style="color: #009900;">&#40;</span>orderNum<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>上例中的注释处代表了一段和orderNum不相关的代码。orderNum的声明和初始化离被使用的地方相隔了很多行的代码，这样做不好，不如这样：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">//do something withou orderNum here</span><br />
<br />
<span style="color: #000066; font-weight: bold;">int</span> orderNum<span style="color: #339933;">=</span> getOrderNum<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
call<span style="color: #009900;">&#40;</span>orderNum<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<h3>4.10 缩小变量的作用域</h3>
<p>能用局部变量的，不要使用实例变量，能用实例变量的，不要使用类变量。变量的生存期越短，以为着它被误用的机会越小，同一时刻程序员要关注的变量的状态越少。实例变量和类变量默认都不是线程安全的，局部变量是线程安全的。比如如下代码：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> OrderPayAction<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> Order order<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; order <span style="color: #339933;">=</span> orderDao.<span style="color: #006633;">findOrder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doJob1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doJob2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> doJob1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doSomething<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> doJob2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doOtherThing<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>上例中order只不过担当了在方法间传递参数之用，用下面的方法更好：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> OrderPayAction<span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; order <span style="color: #339933;">=</span> orderDao.<span style="color: #006633;">findOrder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doJob1<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doJob2<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> doJob1<span style="color: #009900;">&#40;</span>Order order<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doSomething<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">void</span> doJob2<span style="color: #009900;">&#40;</span>Order order<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; doOtherThing<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<h3>4.11 尽量不要用参数来带回方法运算结果</h3>
<p>比如：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> calculate<span style="color: #009900;">&#40;</span>Order order<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">int</span> result <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//do lots of computing and store it in the result</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp; order.<span style="color: #006633;">setResult</span><span style="color: #009900;">&#40;</span>result<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> action<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; order <span style="color: #339933;">=</span> orderDao.<span style="color: #006633;">findOrder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; calculate<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// do lots of things about order</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>例子中calculate方法通过传入的order对象来存储结果， 不如如下写：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">int</span> calculate<span style="color: #009900;">&#40;</span>Order order<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">int</span> result <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//do lots of computing and store it in the result</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> result<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> action<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; order <span style="color: #339933;">=</span> orderDao.<span style="color: #006633;">findOrder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; order.<span style="color: #006633;">setResult</span><span style="color: #009900;">&#40;</span>calculate<span style="color: #009900;">&#40;</span>order<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// do lots of things about order</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/186/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>如何保证jms消息的顺序性</title>
		<link>http://www.sulong.info/archives/183</link>
		<comments>http://www.sulong.info/archives/183#comments</comments>
		<pubDate>Wed, 03 Jun 2009 03:39:58 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[jms]]></category>
		<category><![CDATA[思考]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=183</guid>
		<description><![CDATA[JMS提供的queue和topic两种工作方式，其中queue能保证消息在传输中的顺序性，这是队列先入先出(first in first out)的特性。JMS本身不能保证多个队列里的消息的顺序性，比如 先放入queue1的消息m1，并不一定总是比后放入queue2的消息m2，先到达同样的目的地。 并发地发送和接收消息不能保证消息按正确顺序进入队列和被消费。比如，有两个线程分别发送创建订单和支付订单消息，由于线程运行的不确定性，即使我们按顺序先开始发送创建订单的线程，后开始支付订单的线程，如果两个线程开始时间间隔不够长，还是有可能后开始的线程先发送掉消息。同样的情况发生在并发的接收处理消息时。 那么如何保证消息的顺序性呢？ 一种方案是，乱序接收，顺序处理。也就是说，消息在发送，传输和接收过程中可能是乱序的，但消费者在接收到消息之后，并不立即处理，而是先将消息排序，然后在处理。JMS消息头部的 JMSCorrelationID可以帮助我们完成这个工作。JMSCorrelationID存放了另一个消息的id。消息的发送者，如果要保证消息的顺序性，要将后发送的消息的JMSCorrelationID设置成前一个消息的id。消费者接收消息后，如果发现其头部有JMSCorrelationID，则查看该消息是否已被处理过，如果没有，则等待该消息，至到该消息被处理后，才处理这个消息。这一工作需要发送者和接收者都记住已经发送和接收过的消息，以便于给后来的消息参考。 另一种方案是，顺序发送，顺序传输，顺序接收，顺序处理。其中传输可以由queue来保证，但是发送接收和处理则需要应用程序来控制。简单的说，直到前一个消息发送成功，才能发送后一个消息，同样的，直到前一个消息被接受和处理结束，才能接收和处理后一个消息。这样的做法无疑会降低并发带来的好处。 以上所说的方案，是用来严格控制消息的顺序性的，然而，如果消息的发送的间隔时间足够长，不需要做过多控制，也可以控制消息的顺序性。假设，一个消息正常情况下，由发送，传输，接收到处理成功，最大时间耗费是2秒，那么只要我们保证消息发送的时间隔达不低于2秒，那么这两个消息就可以被正确的处理。这一条件咋听起来很苛刻，但事实上大部分的消息都满足了。比如，同一个订单的创建，和请求支付，最快也要数秒的时间，而退款的开始和结束，可能要数天。在典型的web应用中，操作人员不可能那么快的点击系统，而系统也不可能那么快的响应。进一步的，如果两个需要顺序处理的业务事件可能在极端的时间里连续发生，我们只要在程序上控制，人为将间隔拉开，就可以保证顺序性。 在系统的各各环节控制消息的顺序，代价高昂，而带来的好处却只是针对那极少数极端情况；通过业务或程序的方式，保证消息的有效时间间隔，代价较小，也能有效保证顺序。 如果系统中有很多的间隔极端，又需要保证顺序的消息，那你就要考虑是否将这两个消息合并成一个，或则不该采用jms了。]]></description>
			<content:encoded><![CDATA[<p>JMS提供的queue和topic两种工作方式，其中queue能保证消息在传输中的顺序性，这是队列先入先出(first in first out)的特性。JMS本身不能保证多个队列里的消息的顺序性，比如 先放入queue1的消息m1，并不一定总是比后放入queue2的消息m2，先到达同样的目的地。</p>
<p>并发地发送和接收消息不能保证消息按正确顺序进入队列和被消费。比如，有两个线程分别发送创建订单和支付订单消息，由于线程运行的不确定性，即使我们按顺序先开始发送创建订单的线程，后开始支付订单的线程，如果两个线程开始时间间隔不够长，还是有可能后开始的线程先发送掉消息。同样的情况发生在并发的接收处理消息时。</p>
<p>那么如何保证消息的顺序性呢？</p>
<p>一种方案是，乱序接收，顺序处理。也就是说，消息在发送，传输和接收过程中可能是乱序的，但消费者在接收到消息之后，并不立即处理，而是先将消息排序，然后在处理。JMS消息头部的 JMSCorrelationID可以帮助我们完成这个工作。JMSCorrelationID存放了另一个消息的id。消息的发送者，如果要保证消息的顺序性，要将后发送的消息的JMSCorrelationID设置成前一个消息的id。消费者接收消息后，如果发现其头部有JMSCorrelationID，则查看该消息是否已被处理过，如果没有，则等待该消息，至到该消息被处理后，才处理这个消息。这一工作需要发送者和接收者都记住已经发送和接收过的消息，以便于给后来的消息参考。</p>
<p>另一种方案是，顺序发送，顺序传输，顺序接收，顺序处理。其中传输可以由queue来保证，但是发送接收和处理则需要应用程序来控制。简单的说，直到前一个消息发送成功，才能发送后一个消息，同样的，直到前一个消息被接受和处理结束，才能接收和处理后一个消息。这样的做法无疑会降低并发带来的好处。</p>
<p>以上所说的方案，是用来严格控制消息的顺序性的，然而，如果消息的发送的间隔时间足够长，不需要做过多控制，也可以控制消息的顺序性。假设，一个消息正常情况下，由发送，传输，接收到处理成功，最大时间耗费是2秒，那么只要我们保证消息发送的时间隔达不低于2秒，那么这两个消息就可以被正确的处理。这一条件咋听起来很苛刻，但事实上大部分的消息都满足了。比如，同一个订单的创建，和请求支付，最快也要数秒的时间，而退款的开始和结束，可能要数天。在典型的web应用中，操作人员不可能那么快的点击系统，而系统也不可能那么快的响应。进一步的，如果两个需要顺序处理的业务事件可能在极端的时间里连续发生，我们只要在程序上控制，人为将间隔拉开，就可以保证顺序性。</p>
<p>在系统的各各环节控制消息的顺序，代价高昂，而带来的好处却只是针对那极少数极端情况；通过业务或程序的方式，保证消息的有效时间间隔，代价较小，也能有效保证顺序。</p>
<p>如果系统中有很多的间隔极端，又需要保证顺序的消息，那你就要考虑是否将这两个消息合并成一个，或则不该采用jms了。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/183/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>为什么java没有php开发web容易？</title>
		<link>http://www.sulong.info/archives/176</link>
		<comments>http://www.sulong.info/archives/176#comments</comments>
		<pubDate>Tue, 02 Jun 2009 03:34:17 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=176</guid>
		<description><![CDATA[为什么java没有php开发web容易？原因可能有很多种，就我这半年的php经验来看，主要有以下几点原因： 1. java没有php那样好用的map(在php里叫做array) 这一点很重要，直接看代码吧： php的: $values= array&#40; &#160; &#160; 'login_name'=&#62;'sulong', &#160; &#160; 'password'=&#62;'', &#160; &#160; 'login_result'=&#62;array&#40; &#160; &#160; &#160; &#160; 'error_no'=&#62;3, &#160; &#160; &#160; &#160; 'msg'=&#62; 'account disabled' &#160; &#160; &#41; &#41;; java的: Map values = new HashMap&#40;&#41;; values.put&#40;&#34;login_name&#34;, &#34;sulong&#34;&#41;; values.put&#40;&#34;password&#34;, &#34;&#34;&#41;; Mapresult = new HashMap&#40;&#41;; result.put&#40;&#34;error_no&#34;, &#34;3&#34;&#41;; result. put&#40;&#34;msg&#34;, &#34;account disabled&#34;&#41;; values.put&#40;&#34;login_result&#34;, result&#41;; 很多时候，java程序员宁愿选择建一个新的类来做数据的载体，也就是常说的bean了。但是很多时候，我只想要一个简洁好用的Map而已。 [...]]]></description>
			<content:encoded><![CDATA[<p>为什么java没有php开发web容易？原因可能有很多种，就我这半年的php经验来看，主要有以下几点原因：</p>
<h2>1. java没有php那样好用的map(在php里叫做array)</h2>
<p>这一点很重要，直接看代码吧：<br />
php的:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$values</span><span style="color: #339933;">=</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'login_name'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">'sulong'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; <span style="color: #0000ff;">'password'</span><span style="color: #339933;">=&gt;</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; <span style="color: #0000ff;">'login_result'</span><span style="color: #339933;">=&gt;</span>array<span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'error_no'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'msg'</span><span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'account disabled'</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>java的:</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Amap+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">Map</span></a> values <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ahashmap+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">HashMap</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
values.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;login_name&quot;</span>, <span style="color: #0000ff;">&quot;sulong&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
values.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;password&quot;</span>, <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
Mapresult <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3Ahashmap+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span style="color: #003399;">HashMap</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
result.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;error_no&quot;</span>, <span style="color: #0000ff;">&quot;3&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
result. <span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;msg&quot;</span>, <span style="color: #0000ff;">&quot;account disabled&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
values.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;login_result&quot;</span>, result<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>很多时候，java程序员宁愿选择建一个新的类来做数据的载体，也就是常说的bean了。但是很多时候，我只想要一个简洁好用的Map而已。</p>
<p>最好的是groovy：</p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">values <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><br />
&nbsp; &nbsp; login_name<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;sulong&quot;</span>, <br />
&nbsp; &nbsp; password<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;&quot;</span>, <br />
&nbsp; &nbsp; login_result<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; error_no<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;3&quot;</span>, <br />
&nbsp; &nbsp; &nbsp; &nbsp; msg<span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;account disabled&quot;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#93;</span><br />
<span style="color: #009900;">&#93;</span></div></div>
<p>仅凭这一点，我就觉得在groovy克服其它问题后，必会成为java在web开发上的利器。</p>
<h2>2. java经常要重启服务器</h2>
<p>用java开发web，只要改动了java代码，就要重新启动服务器，至少要重新部署一下应用，才能看到新代码的效果，而php就不需要。所以，开发php的时候，经常是一边写，一边运行看效果，快速的迭代和开发。相比之下，java要不断的编译重新发布，重启服务器，比php慢多了。如果java开发也可以即时生效，不用不断的重启的话，那么java的开发效率必然会有很大的提升。</p>
<h2>3. 动态类型</h2>
<p>确实，动态类型意味这较弱的IDE支持，意味着要进行更多的测试，以避免意想不到的效果，但是，另一方面，动态类型将代码简化，让程序员关注于做什么，而不是怎么做，提升了生产率。比如，用动态类型语言的时候，我们只要说，dog.bark()，那么我们不用关心dog到底是不是dog，只要他能bark()，那bark()就好了。而在静态类型的语言中，我们一定要先搞清楚那是什么，能不能bark,如果不能bark怎么办？是不是要做一层包装？做类型的转换？等等。严谨固然有他的好处，但自由简明显然开发起来更加的快速。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/176/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>企业应用集成&#8211;引入ESB</title>
		<link>http://www.sulong.info/archives/169</link>
		<comments>http://www.sulong.info/archives/169#comments</comments>
		<pubDate>Mon, 11 May 2009 06:44:15 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[esb]]></category>
		<category><![CDATA[思考]]></category>
		<category><![CDATA[经验]]></category>

		<guid isPermaLink="false">http://www.sulong.info/archives/169</guid>
		<description><![CDATA[随着时间的推移，一个企业的业务会越来越复杂，企业应用越来越多，应用间交互越来越复杂。新的应用的开发，耗在集成的上的时间和精力越来越多，而且集成也成了bug最容易发生的地方。如果不能很好的处理好集成问题，开发将很难再进行下去。 如果每个应用之间直接通过jms或http连接，应用数为N，那么最坏情况下，共有N(N-1)/2个连接，随着N的增长，应用间的连接越来越多，集成越来越累。如下图所示: 这个时候使用ESB，可以是系统从网状结构改成总线结构。如下图所示： 每个应用只要做好和ESB的连接，这将大大的降低系统结构的复杂度。ESB将负责路由应用间的消息。路由功能是ESB一个强项，不通过写代码，只要改改配置文件就可以实现简单的简单的路由规则。在网状结构中，每个应用负责决定消息是否发送到什么地方。比如，如果app1需要将消息发送到app2和app3，那么他要主动的和app2,app3连接，发送去消息。而在esb结构中，app1只需要把消息发送到esb上，由esb负责将这个消息路由到app2和app3。这样应用更关心和消息相关的创建和消费的业务功能，而不用关心消息的路由，而esb只关注消息的路由，却不用关注具体的业务逻辑。这样的关注点分离是很有益的。 另一方面，esb支持众多的协议，不仅支持jms, http，还支持比如corba, esb等协议，可以方便的和应用连接上。esb还内置的消息格式的转化内容的增强等功能。这样，app1, app2可以通过不同的协议连接到esb上，而且app1发送的可以是某种二进制报文，而app2接收的却是xml，不同协议的桥接，不同消息的格式和内容的差异，都可以在esb中弥补掉。这一能力对于集成遗留系统非常很有用。 可见esb让应用系统更关注于业务逻辑，而把路由，消息格式内容的转化和不同协议的支持等功能放到统一地方，几乎就是专门为应用集成而生的。]]></description>
			<content:encoded><![CDATA[<p>随着时间的推移，一个企业的业务会越来越复杂，企业应用越来越多，应用间交互越来越复杂。新的应用的开发，耗在集成的上的时间和精力越来越多，而且集成也成了bug最容易发生的地方。如果不能很好的处理好集成问题，开发将很难再进行下去。</p>
<p>如果每个应用之间直接通过jms或http连接，应用数为N，那么最坏情况下，共有N(N-1)/2个连接，随着N的增长，应用间的连接越来越多，集成越来越累。如下图所示:</p>
<p><img src="http://www.sulong.info/wp-content/uploads/2009/05/2009-05-11-1.jpg" alt="struct_without_esb" title="struct_without_esb" width="267" height="216" class="alignnone size-full wp-image-173" /></p>
<p>这个时候使用ESB，可以是系统从网状结构改成总线结构。如下图所示：</p>
<p><img src="http://www.sulong.info/wp-content/uploads/2009/05/20090511-2.jpg" alt="esb" title="esb" width="252" height="267" class="alignnone size-full wp-image-174" /></p>
<p>每个应用只要做好和ESB的连接，这将大大的降低系统结构的复杂度。ESB将负责路由应用间的消息。路由功能是ESB一个强项，不通过写代码，只要改改配置文件就可以实现简单的简单的路由规则。在网状结构中，每个应用负责决定消息是否发送到什么地方。比如，如果app1需要将消息发送到app2和app3，那么他要主动的和app2,app3连接，发送去消息。而在esb结构中，app1只需要把消息发送到esb上，由esb负责将这个消息路由到app2和app3。这样应用更关心和消息相关的创建和消费的业务功能，而不用关心消息的路由，而esb只关注消息的路由，却不用关注具体的业务逻辑。这样的关注点分离是很有益的。</p>
<p>另一方面，esb支持众多的协议，不仅支持jms, http，还支持比如corba, esb等协议，可以方便的和应用连接上。esb还内置的消息格式的转化内容的增强等功能。这样，app1, app2可以通过不同的协议连接到esb上，而且app1发送的可以是某种二进制报文，而app2接收的却是xml，不同协议的桥接，不同消息的格式和内容的差异，都可以在esb中弥补掉。这一能力对于集成遗留系统非常很有用。</p>
<p>可见esb让应用系统更关注于业务逻辑，而把路由，消息格式内容的转化和不同协议的支持等功能放到统一地方，几乎就是专门为应用集成而生的。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/169/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>企业应用集成&#8211;java</title>
		<link>http://www.sulong.info/archives/166</link>
		<comments>http://www.sulong.info/archives/166#comments</comments>
		<pubDate>Tue, 28 Apr 2009 07:34:24 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[jms]]></category>
		<category><![CDATA[思考]]></category>
		<category><![CDATA[经验]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=166</guid>
		<description><![CDATA[java企业应用最终往往运行在某种应用服务器中，比如tomcat，jboss等。部署的单元是war, jar 或者 ear文件，开始的时候，我们可能会将多个应用放到一个单元里来开发管理和部署。随着应用的增多，为了能够让每个应用能够独立的运行不受干扰，也为了开发工作能很好的安排，往往会将各应用分开，于是会有多个war, jar,或ear文件。试想一下，假设你有订单系统，产品系统，客服系统，等，如果这些应用都被放在同一个部署单元里，当需要更新客服系统时，会短暂的导致订单系统不能正常工作，而这种情况往往是不能被接受的。另外，如果客服系统非常繁忙，由于部署在同一台物理服务器上，共享硬件资源，订单系统会受到干扰，而这也不是我们想要的。将单独的应用单独打包，单独部署成为必然。那么就面临着让这些应用通信，将它们集成的问题。 与java和php之间集成相比，java与java之间的集成，不仅可以使用共享数据库，soap，或基于http的简单的文档交换，还可以使用jms，rmi等多种方案。其中jms是j2ee众多的标准中最为成功的协议之一，很少有人针对它发表过不满意见。我们在工作中就采用了jms。和http相比，它有如下优势: 为java量身定做的 jms不仅可以传输普通的字符串，还可以直接传输java对象，并和java的其它服务结合起来，接口api也符合java的使用习惯。如果用http，我们还得要考虑如何把对象序列化等问题，比较麻烦。 使用长连接 http主要用在客户端和服务器交互上，为了能让服务器支持大量的客户端，http往往都以一种无状态和短连接的方式工作。而jms主要用在java应用之间的交互，不需要支持那么多的客户端，用长连接更加适合。典型的http服务器，可能同时要给数千数万人提供服务，如果服务器和每个客户端保持一个连接，那对服务器来说，显然是一个非常大的负担。所以，通常客户端和http的一次交互完成后，连接就断开，而下次访问时，还得要重新建立连接。jms服务器面对的客户端一般只有几个，至多几十个，和每个客户端保持连接的开销是可以接受的。典型的企业可能有如下系统：订单系统，产品系统，结算系统，等等，这些系统，每个都和集中的jms服务器保持一个连接，总连接数也是很少的，所以可以保持长连接。这客户端和jms服务器通信的时候，不必每次都建立连接，减少了网络操作，提升了性能。 异步 http操作的过程是同步的，如果要使用异步的方式工作，需要程序员再做些编码工作。而jms天生就以异步的方式来工作的，不必做过多的编码。消息的生产者一旦把消息发送出去，就可以立刻返回不必等待消息的消费结果，后续的消息消费可以自动的异步执行。将不必要立刻执行的动作异步执行，可以大大降低系统的响应时间。 可靠的消息传递 在使用http通信的过程中，如果发生了网络异常，是否要做重发，以及如何重发，会是一件很痛苦的事情。jms提供了persitent的传递模式，在这种模式时，客户端代理在发送消息之前，会先把消息持久，如果发生网络异常，客户端代理会自动处理重发，而不需要应用程序关心。jms消息的唯一编号，可以有效的阻止一个消息被重复处理的问题。 在java应用集成时，jms比http更适合。成熟的jms服务器软件很多，除了ibm的mq，jboss mq, apache activemq 都是很不错的选择。]]></description>
			<content:encoded><![CDATA[<p>java企业应用最终往往运行在某种应用服务器中，比如tomcat，jboss等。部署的单元是war, jar 或者 ear文件，开始的时候，我们可能会将多个应用放到一个单元里来开发管理和部署。随着应用的增多，为了能够让每个应用能够独立的运行不受干扰，也为了开发工作能很好的安排，往往会将各应用分开，于是会有多个war, jar,或ear文件。试想一下，假设你有订单系统，产品系统，客服系统，等，如果这些应用都被放在同一个部署单元里，当需要更新客服系统时，会短暂的导致订单系统不能正常工作，而这种情况往往是不能被接受的。另外，如果客服系统非常繁忙，由于部署在同一台物理服务器上，共享硬件资源，订单系统会受到干扰，而这也不是我们想要的。将单独的应用单独打包，单独部署成为必然。那么就面临着让这些应用通信，将它们集成的问题。<br />
<br/><br />
与java和php之间集成相比，java与java之间的集成，不仅可以使用共享数据库，soap，或基于http的简单的文档交换，还可以使用jms，rmi等多种方案。其中jms是j2ee众多的标准中最为成功的协议之一，很少有人针对它发表过不满意见。我们在工作中就采用了jms。和http相比，它有如下优势:</p>
<h3>为java量身定做的</h3>
<p>jms不仅可以传输普通的字符串，还可以直接传输java对象，并和java的其它服务结合起来，接口api也符合java的使用习惯。如果用http，我们还得要考虑如何把对象序列化等问题，比较麻烦。</p>
<h3>使用长连接</h3>
<p>http主要用在客户端和服务器交互上，为了能让服务器支持大量的客户端，http往往都以一种无状态和短连接的方式工作。而jms主要用在java应用之间的交互，不需要支持那么多的客户端，用长连接更加适合。典型的http服务器，可能同时要给数千数万人提供服务，如果服务器和每个客户端保持一个连接，那对服务器来说，显然是一个非常大的负担。所以，通常客户端和http的一次交互完成后，连接就断开，而下次访问时，还得要重新建立连接。jms服务器面对的客户端一般只有几个，至多几十个，和每个客户端保持连接的开销是可以接受的。典型的企业可能有如下系统：订单系统，产品系统，结算系统，等等，这些系统，每个都和集中的jms服务器保持一个连接，总连接数也是很少的，所以可以保持长连接。这客户端和jms服务器通信的时候，不必每次都建立连接，减少了网络操作，提升了性能。</p>
<h3>异步</h3>
<p>http操作的过程是同步的，如果要使用异步的方式工作，需要程序员再做些编码工作。而jms天生就以异步的方式来工作的，不必做过多的编码。消息的生产者一旦把消息发送出去，就可以立刻返回不必等待消息的消费结果，后续的消息消费可以自动的异步执行。将不必要立刻执行的动作异步执行，可以大大降低系统的响应时间。</p>
<h3>可靠的消息传递</h3>
<p>在使用http通信的过程中，如果发生了网络异常，是否要做重发，以及如何重发，会是一件很痛苦的事情。jms提供了persitent的传递模式，在这种模式时，客户端代理在发送消息之前，会先把消息持久，如果发生网络异常，客户端代理会自动处理重发，而不需要应用程序关心。jms消息的唯一编号，可以有效的阻止一个消息被重复处理的问题。<br />
<br/></p>
<p>在java应用集成时，jms比http更适合。成熟的jms服务器软件很多，除了ibm的mq，jboss mq, apache activemq 都是很不错的选择。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/166/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>企业应用集成&#8211;java与php</title>
		<link>http://www.sulong.info/archives/162</link>
		<comments>http://www.sulong.info/archives/162#comments</comments>
		<pubDate>Thu, 23 Apr 2009 03:18:56 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[思考]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[集成]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=162</guid>
		<description><![CDATA[随着企业的发展，企业的业务种类越来越多，业务量越来越大，越来越复杂，部署在单一的服务器上的单一的应用很难再满足业务系统在可靠性，性能，易于维护和扩展等很多方面的需求。进而把企业系统拆分成很多的独立应用，部署在多台服务器上，成为必须。拆分开的多个应用并不能独立的完成所有的业务，应用间必然需要集成。用什么样的方式把各应用集成，不仅能满足系统的功能需要，还能做到易于维护，易于扩展，高性能，高可靠，就成为了一个难题。 公司最开始用php做所有的内部(指面向公司内部职员)和外部的应用（外部指面向internet用户的），之后公司开始采用java来逐步代替php来开发内部应用。所以，我们java程序不但面临着如何集成java内部的各个应用的问题，还面临着如何和php集成的问题。我们使用用过以下方法和php集成： 数据库共享： java和php使用相同的数据库，为了减少混乱，同一张表，只能由java或php其中一方负责写。这种方法使用起来直观，易用，但还是有很多的问题。 首先，java和php对数据库的一些行为是不一致的。mysql数据库的datatime类型，再插入不正确的数据时，mysql会在里面插入&#8221;0000-00-00 00:00:00&#8243;, php在读取这样的日期时没有问题，反正，他是字符串。但是java这边却会出错，应为jdbc会默认的将它转化成java.sql.Date类型，而在转化的是时候会发生异常。更大的阻力来自于php和java两个团队在使用数据库习惯上的差异。 其次，数据库共享功能不够强。比如，php完成某个业务时，需要及时通知java，但是仅通过数据库共享不好做，除非java对数据库轮询，但这样做显然很难在及时性和性能两者之间找到平衡。 再次，可扩展性差，但需要做出变更时，变更数据库显然是一件更加痛苦的事。这不仅要处理遗留的数据，还要调节两边的数据库访问程序。 所以，正是后续的项目里就没有再使用过这一方案。 SOAP： 按理说soap这种语言中立又规范化的技术应该非常适合于这种场景，但是在使用过程中还是会出现很多的问题。 首先，php和java两边对soap的理解并不一样。Java生成的布尔值在soap的xml里并表示为true或则false，但是在php看来只要不是0，都是true，所以&#8221;false&#8221;也是true。也许是php那边所使用的soap支持程序有问题，但是这个问题确实给我们带来了很多麻烦。还有一个要命的问题，就是字符集的问题，php以前一直使用gb2312和gb18030，但是soap的xml并不支持gb18030里的某些奇特字符，一旦遇到这样的字符，xml解析就失败。后来，不得不把可能出现此类字符的内容用base64编码。顺便发一下牢骚，这些奇怪的字符网网都来自于那些爱使用脑残体火星文的新新人类，这些人简直就是弱智！ 基于http的简单文档交互: 这种方法很简单，就是通过http post个xml或其它文档来实现交互。这种方式就是原始的使用http的soap，只是soap后来加了一大堆的标准（ws-*），在这些标准对我们来说没有意义，而php和java两边对标准的支持不兼容的时候，soap就成了鸡肋。后来，我们就干脆抛弃了soap，而通过我们自己的程序来发送和接收我们自定义的没有歧义的xml。目前为止，这是两边都乐意使用且很少出问题的方式。这种方式需要两边很好的配合，需要规范化的文档，否则以后只会变得混乱。 我们也曾想过使用基于java的php实现，来达到让java和php在语言级别集成，这种方法对于php遗留系统来说风险太大，而且php程序员面并不乐意生活在java的虚拟机内。也许未来这能成为一个成熟的方案。 正因为使用不同技术的应用之间的集成存在很多的问题，在实际项目中应该尽量避免。]]></description>
			<content:encoded><![CDATA[<p>随着企业的发展，企业的业务种类越来越多，业务量越来越大，越来越复杂，部署在单一的服务器上的单一的应用很难再满足业务系统在可靠性，性能，易于维护和扩展等很多方面的需求。进而把企业系统拆分成很多的独立应用，部署在多台服务器上，成为必须。拆分开的多个应用并不能独立的完成所有的业务，应用间必然需要集成。用什么样的方式把各应用集成，不仅能满足系统的功能需要，还能做到易于维护，易于扩展，高性能，高可靠，就成为了一个难题。</p>
<p>公司最开始用php做所有的内部(指面向公司内部职员)和外部的应用（外部指面向internet用户的），之后公司开始采用java来逐步代替php来开发内部应用。所以，我们java程序不但面临着如何集成java内部的各个应用的问题，还面临着如何和php集成的问题。我们使用用过以下方法和php集成：</p>
<h3>数据库共享：</h3>
<p>java和php使用相同的数据库，为了减少混乱，同一张表，只能由java或php其中一方负责写。这种方法使用起来直观，易用，但还是有很多的问题。<br />
首先，java和php对数据库的一些行为是不一致的。mysql数据库的datatime类型，再插入不正确的数据时，mysql会在里面插入&#8221;0000-00-00 00:00:00&#8243;, php在读取这样的日期时没有问题，反正，他是字符串。但是java这边却会出错，应为jdbc会默认的将它转化成java.sql.Date类型，而在转化的是时候会发生异常。更大的阻力来自于php和java两个团队在使用数据库习惯上的差异。<br />
其次，数据库共享功能不够强。比如，php完成某个业务时，需要及时通知java，但是仅通过数据库共享不好做，除非java对数据库轮询，但这样做显然很难在及时性和性能两者之间找到平衡。<br />
再次，可扩展性差，但需要做出变更时，变更数据库显然是一件更加痛苦的事。这不仅要处理遗留的数据，还要调节两边的数据库访问程序。<br />
所以，正是后续的项目里就没有再使用过这一方案。</p>
<h3>SOAP：</h3>
<p>按理说soap这种语言中立又规范化的技术应该非常适合于这种场景，但是在使用过程中还是会出现很多的问题。<br />
首先，php和java两边对soap的理解并不一样。Java生成的布尔值在soap的xml里并表示为true或则false，但是在php看来只要不是0，都是true，所以&#8221;false&#8221;也是true。也许是php那边所使用的soap支持程序有问题，但是这个问题确实给我们带来了很多麻烦。还有一个要命的问题，就是字符集的问题，php以前一直使用gb2312和gb18030，但是soap的xml并不支持gb18030里的某些奇特字符，一旦遇到这样的字符，xml解析就失败。后来，不得不把可能出现此类字符的内容用base64编码。顺便发一下牢骚，这些奇怪的字符网网都来自于那些爱使用脑残体火星文的新新人类，这些人简直就是弱智！</p>
<h3>基于http的简单文档交互:</h3>
<p>这种方法很简单，就是通过http post个xml或其它文档来实现交互。这种方式就是原始的使用http的soap，只是soap后来加了一大堆的标准（ws-*），在这些标准对我们来说没有意义，而php和java两边对标准的支持不兼容的时候，soap就成了鸡肋。后来，我们就干脆抛弃了soap，而通过我们自己的程序来发送和接收我们自定义的没有歧义的xml。目前为止，这是两边都乐意使用且很少出问题的方式。这种方式需要两边很好的配合，需要规范化的文档，否则以后只会变得混乱。</p>
<p>我们也曾想过使用基于java的php实现，来达到让java和php在语言级别集成，这种方法对于php遗留系统来说风险太大，而且php程序员面并不乐意生活在java的虚拟机内。也许未来这能成为一个成熟的方案。</p>
<p>正因为使用不同技术的应用之间的集成存在很多的问题，在实际项目中应该尽量避免。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/162/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>推荐个很不错图形化keytool</title>
		<link>http://www.sulong.info/archives/153</link>
		<comments>http://www.sulong.info/archives/153#comments</comments>
		<pubDate>Tue, 10 Feb 2009 07:36:54 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[keytool]]></category>
		<category><![CDATA[技巧]]></category>

		<guid isPermaLink="false">http://www.sulong.info/archives/153</guid>
		<description><![CDATA[Java的keytool命令实在是太不好用了，尤其是缺少这方面知识的时候。今题找到了一个keytool的图形化前端，非常好用！在这里记下，强烈推荐！ http://yellowcat1.free.fr/keytool_iui.html]]></description>
			<content:encoded><![CDATA[<p>Java的keytool命令实在是太不好用了，尤其是缺少这方面知识的时候。今题找到了一个keytool的图形化前端，非常好用！在这里记下，强烈推荐！</p>
<p>http://yellowcat1.free.fr/keytool_iui.html</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/153/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaEE组件的并发与无状态</title>
		<link>http://www.sulong.info/archives/146</link>
		<comments>http://www.sulong.info/archives/146#comments</comments>
		<pubDate>Mon, 05 Jan 2009 12:22:00 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[技巧]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[java EE]]></category>
		<category><![CDATA[经验]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=146</guid>
		<description><![CDATA[并发与线程安全 串行运行时正确的程序在并发运行时可能会出错，这是由于并发运行的多个任务（进程或线程）之间共享了变量。在Java EE环境下很多的组件最终都是在多线程环境下并发运行的，应该牢记住这一点，避免发生诡异的错误。在上个项目中，我们的程序就出现过诡异的错误，在并发量小的测试环境下，它很少出现，但是随着并发量的增大，它出现的次数增多。经查，发现如下类似代码: &#160; &#160; public class SomeServlet extends HttpServlet &#123; &#160; &#160; &#160; &#160; private SomeType someVariable; &#160; &#160; &#160; &#160; public void doPost&#40;HttpServletRequest req, HttpServletRespons rsp&#41; &#123; &#160; &#160; &#160; &#160; &#160; &#160; method1&#40;&#41;; &#160; &#160; &#160; &#160; &#160; &#160; method2&#40;&#41;; &#160; &#160; &#160; &#160; &#125; &#160; &#160; &#160; &#160; void method1&#40;&#41; &#123; [...]]]></description>
			<content:encoded><![CDATA[<h3>并发与线程安全</h3>
<p>串行运行时正确的程序在并发运行时可能会出错，这是由于并发运行的多个任务（进程或线程）之间共享了变量。在Java EE环境下很多的组件最终都是在多线程环境下并发运行的，应该牢记住这一点，避免发生诡异的错误。在上个项目中，我们的程序就出现过诡异的错误，在并发量小的测试环境下，它很少出现，但是随着并发量的增大，它出现的次数增多。经查，发现如下类似代码:<br/></p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SomeServlet <span style="color: #000000; font-weight: bold;">extends</span> HttpServlet <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> SomeType someVariable<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doPost<span style="color: #009900;">&#40;</span>HttpServletRequest req, HttpServletRespons rsp<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; method1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; method2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">void</span> method1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006633;">someVariable</span> <span style="color: #339933;">=</span> someValue<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">void</span> method2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006633;">someVariable</span> <span style="color: #339933;">=</span> someValue<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>method1() 和method2()都访问到了someVariable，而且程序员的本意是想在method2()使用由method1()产生的 someVariable，但是Servlet可能被多个线程共享，上面的代码不能正常工作。当Servlet容器用thread1和thread2两个线程来服务两个请求request1和request2，而thread1和thread2使用了同一个SomeServlet对象，如果JVM在 SomeServlet在执行到method1()后和method2()前时发生线程间的切换，那么就很可能导致出错，比如：thread1.method1()->thread2.method1()->thread1.method2()->thread2.method2()。实例变量和类变量都是在线程间共享的，而方法内的局部变量和参数是不会被共享的，所以要处理这个问题，最简单的方法是通过方法参数来传递 someVariable，而不是通过实例变量。所以这段程序改成这样就可以了：<br/></p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SomeServlet <span style="color: #000000; font-weight: bold;">extends</span> HttpServlet <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> doPost<span style="color: #009900;">&#40;</span>HttpServletRequest req, HttpServletRespons rsp<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SomeType someVariable <span style="color: #339933;">=</span> method1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; method2<span style="color: #009900;">&#40;</span>someVariable <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; SomeType someVariablemethod1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> someValue<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">void</span> method2<span style="color: #009900;">&#40;</span>SomeType someVariable<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006633;">someVariable</span> <span style="color: #339933;">=</span> someValue<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>通过synchronized等并发访问控制机制也可以解决这个问题，但是我觉得上面的方式是最直观的。也许有人会说后面的代码比前面的看起来要难看，不够面向对象。这里不讨论怎样才是面向对象，或者面向对象好不好。总之后者是正确的，前者是错误的，没有正确性的程序是没有意义的。<br/></p>
<p>被过线程共享而不会出错的对象，被称之为线程安全的。显然Servlet不是线程安全的，而且还有很多组件也不是线程安全的，比如HttpSession。在上个项目中，我们使用JAXB来处理XML，每次使用时都创建一个JAXBContext对象，后来发现创建JAXBContext的代价是相当的高，于是我们想把它缓存起来在整个应用程序范围内使用，幸好我们使用的JAXBContext的实现是线程安全的，可以放心的被多个线程共享。<br/></p>
<h3>有状态与无状态</h3>
<p>有状态组件是这样一种组件，组件调用者的返回结果会依赖于这个组件之前或正在受到的调用。无状态的组件则相反，调用者的返回结果只和本次调用相关，所有调用者的调用过程不会影响到其他调用者。举例来说，someComponent组件的getLatestCaller()返回上一次的调用者，这个行为的返回值总会和上一次的调用者相关，这样的组件就是有状态的。假如有个组件math有个方法为add(x,y)，返回x+y的值，那么无论之前被哪个调用者调用过，math.add()的返回值只和本次调用的参数相关，这样的组件是无状态的。无状态的组件是线程安全的，因为被别的调用者调用并不会影响到本次的调用结果。</p>
<p>除非有必要，否则应当尽量把你的程序组件实现成无状态的。在spring, seam, ejb里都有无状态的组件。不同的框架在如何实现无状态方面各不相同。最简单的实现方法就是为无状态组件做一个包装，每次调用组件的方法时，都由包装类生成一个新的对象来处理，这样实际上就不再任何的调用者之间共享被调用者的实例，实现了无状态。比如：<br/></p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> SomeInterface <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> SomeType doMyBusinness<span style="color: #009900;">&#40;</span>SomeArg arg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SomeStatlessComponent <span style="color: #000000; font-weight: bold;">implements</span> SomeInterface <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> SomeType doMyBusinness<span style="color: #009900;">&#40;</span>SomeArg arg<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> SomeStatlessComponentWrapper <span style="color: #000000; font-weight: bold;">implements</span> SomeInterface <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> SomeType doMyBusinness<span style="color: #009900;">&#40;</span>SomeArg arg<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">new</span> SomeStatlessComponent<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">doMyBusinness</span><span style="color: #009900;">&#40;</span>arg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>如果实例化组件的代价是昂贵的，用一个对象池缓存组件实例，并在每次从池中取对象时清空对象的状态可能是个更好的办法。其实只要遵循简单的原则，就很容易实现无状态，就是不使用实例变量或类变量，或者只使用只读的实例变量或只读类变量。这样的组件用单例就可以实先无状态。<br/></p>
<p>由于实现上的差别，有些框架根本就不会做过多的努力来保证组件的无状态性，相反他们把责任交给了程序员。作为组件的创作者，如果你确定你要的是无状态的组件，那么只使用只读的实例变量或类变量，是个明智的选择。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/146/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>王者归来之Seam ?!</title>
		<link>http://www.sulong.info/archives/135</link>
		<comments>http://www.sulong.info/archives/135#comments</comments>
		<pubDate>Thu, 18 Dec 2008 04:58:38 +0000</pubDate>
		<dc:creator>imlsq</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[jboss]]></category>
		<category><![CDATA[seam]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=135</guid>
		<description><![CDATA[王者归来之Seam??!!! 前言： seam :  以前在项目开发的过程中，你需要引入很多框架（比如：hibernate, jsf , 工作流引擎&#8230;.) ,  JBOSS说，你们自己做整合，不专业，我来帮你们做了这个工作吧，我来整合，肯定比你们自己整合要好。于此，JBOSS招兵买马，把hibernate的核心团队，JSF规范制定核心团队，EJB3规范制定核心团队等等，都找来当咨询顾问，共讨整合之事，如此诞生了一个新宝宝,取名为SEAM 使用Seam已经有1个多月的时间了，对Seam有一些简单的了解，谈谈我对Seam的一点感想吧。Seam的目标就是把各种优秀的开源系统，J2EE规范，都通过seam这个框架整合起来，从而简化开发工作，提高开发效率。我想这是seam的目标。 seam亮点： 1  JSF和EJB3.0规范实现与整合是亮点之一。 seam实现了SUN公司JSF规范做了不错的工作，在开发JSF应用时，简化了一些JSF。 Seam框架试图简化JSF的开发比如JSF的异常处理，XML配置，JSF组件的调用等等，在开发的时候让JSF和后端的业务逻辑组件(business service bean)达到紧凑，易用的效果。 2 Seam 很有意思的组件管理 我没有去看seam的源代码，但是从seam的介绍文档里有一些简要的介绍，如果有说得不对的地方，仅为交流。 Seam有2种方式来管理组件，一种为了跟JSF，JSP, servlet 等接口，seam 在web.xml 里添加了一个SeamListener，把JSF所需要的组件实例缓存到ServletContext或者HttpSession中，当请求完成或者Session失效时销毁组件实例. 另一种方式是Seam业务组件，这个组件的生命周期管理，类似EJB3规范里规定的方式,Seam业务组件的生命周期管理是否就是EJB3组件规范的实现，还是有自己的管理方式，这些方面的问题，将在以后再去深入了解。 总之，有了对组件的生命周期管理，您不需要去关心事务，并发，同步等问题。我一直都觉得EJB3的组件生命周期管理，比Spring的实现要舒服很多(Spring的组件生命周期管理，还要实现Spring 的InitializingBean,DisposableBean 这2个类,EJB3的组件就是一个很干净的POJO)。 3 Hibernate，Seam中集成的经典JPA EJB3的JPA规范，作为EJB3的重要组成部分，Seam中对此规范的实现，整合了Hibernate3. 在使用的过程中，好像针对Hibernate3做了一些优化,让您在开发过程中，使用hibernate3更加简单一些了。 EJB2的持久化方案，在过去的几年，被hibernate3之前的版本彻底打败，EJB3开始, 这2家冤家对头，居然走到了一起。在ejb3的JPA规范发布不久，Hibernate就开始支持这一规范, 以前的相互指责，现在变成相互吹捧。 (题外话：其实我在做项目的过程中是很不喜欢hibernate的，不是因为他能提高效率的话，早就抛弃它了。我更喜欢ibatis一些，都是手工写的SQL代码做成映射关系，效率提高很多，可惜他现在对ejb3规范还不支持。虽然开发的时候会多写一点代码，那可是值得的) Seam真的是王者归来，我见未必。让我们跳出SEAM看seam。 不要看seam的介绍文档说得多好听，好比一个人自己说自己多厉害一样，没用，还是要人家去评价才行。 在你使用seam之前，请仔细评估自己的需求，是否需要使用他。 1，你的项目是否需要使用EJB？ SEAM 在文档里有说明，SEAM也可以开发类似struts+spring+hibernate一样的轻量级架构的系统，但是那是胡说八道。我可以负责任的告诉 你，seam是一个很重的架构，他大多数的技术体系都是偏重于EJB，用他开发SSH类似的系统，只会误事误工。 2, JSF是否适合你的项目？ JSF 是SUN公司主推的一种表示层解决方案。可惜生不逢时，用JSF做企业应用，有Flex,Silverlight等技术比他强。 用JSF做WEB网页方向的应用，JSF更是滑稽可笑。也许有人说，JSF跟Seam有什么关系？但是我告诉你,seam核心目标之一就是整合JSF做表 示层开发，是他整合目标的重要组成部分。如果你打算应用seam，那么表示层的开发就一定绕不过JSF这一关。尽管seam说，他不用JSF也可以，但是 不用JSF，用什么！！ 没有其它好的选择了。 3,开发效率低 [...]]]></description>
			<content:encoded><![CDATA[<p>王者归来之Seam??!!!</p>
<p>前言：<br />
seam :  以前在项目开发的过程中，你需要引入很多框架（比如：hibernate, jsf , 工作流引擎&#8230;.) ,  JBOSS说，你们自己做整合，不专业，我来帮你们做了这个工作吧，我来整合，肯定比你们自己整合要好。于此，JBOSS招兵买马，把hibernate的核心团队，JSF规范制定核心团队，EJB3规范制定核心团队等等，都找来当咨询顾问，共讨整合之事，如此诞生了一个新宝宝,取名为SEAM</p>
<p>使用Seam已经有1个多月的时间了，对Seam有一些简单的了解，谈谈我对Seam的一点感想吧。Seam的目标就是把各种优秀的开源系统，J2EE规范，都通过seam这个框架整合起来，从而简化开发工作，提高开发效率。我想这是seam的目标。</p>
<p>seam亮点：</p>
<p>1  JSF和EJB3.0规范实现与整合是亮点之一。</p>
<p>seam实现了SUN公司JSF规范做了不错的工作，在开发JSF应用时，简化了一些JSF。 Seam框架试图简化JSF的开发比如JSF的异常处理，XML配置，JSF组件的调用等等，在开发的时候让JSF和后端的业务逻辑组件(business service bean)达到紧凑，易用的效果。</p>
<p>2 Seam 很有意思的组件管理</p>
<p>我没有去看seam的源代码，但是从seam的介绍文档里有一些简要的介绍，如果有说得不对的地方，仅为交流。<br />
Seam有2种方式来管理组件，一种为了跟JSF，JSP, servlet 等接口，seam 在web.xml 里添加了一个SeamListener，把JSF所需要的组件实例缓存到ServletContext或者HttpSession中，当请求完成或者Session失效时销毁组件实例.</p>
<p>另一种方式是Seam业务组件，这个组件的生命周期管理，类似EJB3规范里规定的方式,Seam业务组件的生命周期管理是否就是EJB3组件规范的实现，还是有自己的管理方式，这些方面的问题，将在以后再去深入了解。<br />
总之，有了对组件的生命周期管理，您不需要去关心事务，并发，同步等问题。我一直都觉得EJB3的组件生命周期管理，比Spring的实现要舒服很多(Spring的组件生命周期管理，还要实现Spring 的InitializingBean,DisposableBean 这2个类,EJB3的组件就是一个很干净的POJO)。</p>
<p>3 Hibernate，Seam中集成的经典JPA</p>
<p>EJB3的JPA规范，作为EJB3的重要组成部分，Seam中对此规范的实现，整合了Hibernate3. 在使用的过程中，好像针对Hibernate3做了一些优化,让您在开发过程中，使用hibernate3更加简单一些了。</p>
<p>EJB2的持久化方案，在过去的几年，被hibernate3之前的版本彻底打败，EJB3开始, 这2家冤家对头，居然走到了一起。在ejb3的JPA规范发布不久，Hibernate就开始支持这一规范, 以前的相互指责，现在变成相互吹捧。</p>
<p>(题外话：其实我在做项目的过程中是很不喜欢hibernate的，不是因为他能提高效率的话，早就抛弃它了。我更喜欢ibatis一些，都是手工写的SQL代码做成映射关系，效率提高很多，可惜他现在对ejb3规范还不支持。虽然开发的时候会多写一点代码，那可是值得的)</p>
<p>Seam真的是王者归来，我见未必。让我们跳出SEAM看seam。</p>
<p>不要看seam的介绍文档说得多好听，好比一个人自己说自己多厉害一样，没用，还是要人家去评价才行。 在你使用seam之前，请仔细评估自己的需求，是否需要使用他。</p>
<p>1，你的项目是否需要使用EJB？</p>
<p>SEAM 在文档里有说明，SEAM也可以开发类似struts+spring+hibernate一样的轻量级架构的系统，但是那是胡说八道。我可以负责任的告诉 你，seam是一个很重的架构，他大多数的技术体系都是偏重于EJB，用他开发SSH类似的系统，只会误事误工。</p>
<p>2, JSF是否适合你的项目？</p>
<p>JSF 是SUN公司主推的一种表示层解决方案。可惜生不逢时，用JSF做企业应用，有Flex,Silverlight等技术比他强。 用JSF做WEB网页方向的应用，JSF更是滑稽可笑。也许有人说，JSF跟Seam有什么关系？但是我告诉你,seam核心目标之一就是整合JSF做表 示层开发，是他整合目标的重要组成部分。如果你打算应用seam，那么表示层的开发就一定绕不过JSF这一关。尽管seam说，他不用JSF也可以，但是 不用JSF，用什么！！ 没有其它好的选择了。</p>
<p>3,开发效率低</p>
<p>呵呵，seam说我的开发效率很高嘛，但那是他自己说的嘛，seam开发环境只能在Jboss里运行才有良好的表现，Jboss在开发,调试,部署还是非常麻烦，和tomcat比效率低很多。</p>
<p>4,学习成本</p>
<p>seam引入了很多相关的其它框架包，假设你有良好的JAVA基础，一个未使用过seam的开发团队，熟悉seam起码也要3周以上的时间，这是我见过的学习成本最高的框架,他整合的框架很多，技术面很广.</p>
<p>5，大型系统的解决方案，seam还是无法提供</p>
<p>一个大型的系统，核心的关键点是：负载均衡，集中缓存处理，并行计算， 分布式存取等， seam面对这些问题，一样显得力不从心，这些问题还是需要架构师自己动手解决。而且seam中有一个web beans的技术(我在想，他使用这个是否考虑到整合JSF才这么做呢！)，给负载均衡, session的处理还不及其它框架灵活。</p>
<p>Seam是否是归来的王者？ 让我们拭目以待！</p>
<p>文章内容只是个人之见，肤浅之处，意在交流。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/135/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
