﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-java -- far fly-随笔分类-java入门</title><link>http://www.blogjava.net/john_yu/category/6615.html</link><description>正在学习中：（</description><language>zh-cn</language><lastBuildDate>Wed, 07 Mar 2007 14:11:52 GMT</lastBuildDate><pubDate>Wed, 07 Mar 2007 14:11:52 GMT</pubDate><ttl>60</ttl><item><title>单点登录简单实现</title><link>http://www.blogjava.net/john_yu/archive/2006/11/16/81408.html</link><dc:creator>john</dc:creator><author>john</author><pubDate>Wed, 15 Nov 2006 16:23:00 GMT</pubDate><guid>http://www.blogjava.net/john_yu/archive/2006/11/16/81408.html</guid><wfw:comment>http://www.blogjava.net/john_yu/comments/81408.html</wfw:comment><comments>http://www.blogjava.net/john_yu/archive/2006/11/16/81408.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/john_yu/comments/commentRss/81408.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/john_yu/services/trackbacks/81408.html</trackback:ping><description><![CDATA[<span class="h1b">单点登录的简单实现</span>
		<br />
		<br />
		<!-- 提取技术文章 -->
		<div class="beas">
				<img height="1" alt="" src="http://dev2dev.bea.com.cn/images/dot6B6B6B.gif" width="100%" />
		</div>
		<p>　　在门户项目中，经常会遇到如何实现单点登录的问题，下面就本人的经验做个总结。欢迎大家进行补充讨论。</p>
		<h3>单点登录的具体实现有很多种选择，包括：</h3>
		<ol>
				<li>采用专门的SSO商业软件： 主要有：Netgrity的Siteminder，已经被CA收购。Novell 公司的iChain。RSA公司的ClearTrust等。 
</li>
				<li>采用门户产品供应商自己的SSO产品，如：BEA的WLES，IBM 的Tivoli Access Manager，Sun 公司的identity Server，Oracle公司的OID等。 
</li>
				<li>这些商业软件一般适用于客户对SSO的需求很高，并且企业内部采用COTS软件如：Domino,SAP,Sieble的系统比较多的情况下采用。并结合身份管理。统一认证等项目采用。采用这些软件一般都要对要集成的系统做些改造，如在要集成的系统上安装AGENT。现在一般只提供常见软件如：Domino,SAP,Sieble，常见应用服务器：weblogic,websphere等的AGENT。要先统一这些系统的认证。一般采用LDAP或数据库。然后才能实现SSO。比较麻烦。 
</li>
				<li>另外，如果不想掏银子，也有OPEN SOURCE的SSO软件可选：主要有：<a href="http://www.josso.org/" target="_blank">http://www.josso.org/</a><a href="https://opensso.dev.java.net/" target="_blank">https://opensso.dev.java.net/</a><a href="http://www.sourceid.org/" target="_blank">http://www.sourceid.org</a> 等。具体怎么样就不清楚了。 </li>
		</ol>
		<p>　　如果项目对SSO的要求比较低，又不想对要被集成的系统做任何改动，可采用下面介绍的方式简单实现：下面我们通过一个例子来说明。假如一个门户项目要对下面的几个系统做SSO。</p>
		<p align="center">
				<img height="351" alt="图一" src="http://dev2dev.bea.com.cn/images/image060228002.gif" width="554" border="0" />
		</p>
		<p>　　用户在这些系统中的用户名，密码各不相同，如：员工号为001的员工在这些系统中的用户名，密码分别如下：</p>
		<table class="tabel-general" cellspacing="0" cellpadding="0" width="100%" align="center">
				<tbody>
						<tr>
								<th class="left">用户</th>
								<th class="center">系统</th>
								<th class="center">用户名</th>
								<th class="right">密码</th>
						</tr>
						<tr>
								<td>001</td>
								<td>Portal系统</td>
								<td>A</td>
								<td class="right">1234</td>
						</tr>
						<tr>
								<td>001</td>
								<td>邮件系统</td>
								<td>B</td>
								<td class="right">2345</td>
						</tr>
						<tr>
								<td>001</td>
								<td>DOMINO系统</td>
								<td>C</td>
								<td class="right">AAAA</td>
						</tr>
						<tr>
								<td>001</td>
								<td>报销系统</td>
								<td>D</td>
								<td class="right">CCCC</td>
						</tr>
						<tr>
								<td>001</td>
								<td>工资系统</td>
								<td>E</td>
								<td class="right">BBBB</td>
						</tr>
				</tbody>
		</table>
		<h4>首先，建立员工在PORTAL系统中的用户名和其他系统中的用户名之间的对应关系 </h4>
		<p>　　首先，要建立员工在PORTAL系统中的用户名和其他系统中的用户名之间的对应关系并保存。可保存在表中或LDAP中或文件系统中。当然要考虑这些系统之间的数据同步问题。比较好的方式是找到用户在这些系统中的都存在的唯一信息（如员工号，MAIL地址，姓名等）。通过唯一信息实时到各个系统中去取认证所需要的信息。就不需要考虑数据同步问题。比较实用。可以建立类似下面的表：密码可采用加密保存。如果是采用BEA的Weblogic Portal,可采用UUP来保存这些信息。</p>
		<pre class="code">	(
	
	user	 varchar2(20),   	/*用户名*/
	app_name varchar2(20),  	/*应用系统*/
	architect varchar2(4),  		/*应用系统的架构BS或CS*/
	app_company varchar2(50),          /*用户所属分公司*/
	app_department varchar2(50),      /*用户所在的部门*/
	app_user varchar2(15),                 /*在该系统中的用户名*/
	app_passwd varchar2(15), 	/*在该系统中的密码*/
	app_cookie varchar2(30),              /*COOKIE名称*/
	form_user varchar2(20),                /*认证页面中FORM的用户名字段*/
	form_passwd varchar2(20),          /*认证页面中FORM的密码字段*/
	app_special  varchar2(20)           /*其他*/
	);
</pre>
		<h4>通过IFRAME或超连接方式集成目标系统，并进行SSO</h4>
		<p>　　通过IFRAME或超连接方式集成目标系统,并在URL中带上用户名和密码。如集成DOMINO可采用如下方式：</p>
		<p>　　&lt;IFRAME src=<a href="http://host1/names.nsf?Login&amp;Username=admin&amp;Password=pass&amp;RedirectTo=/names.nsf" target="_parent">http://host1/names.nsf?Login&amp;Username=admin&amp;Password=pass&amp;RedirectTo=/names.nsf</a><br />width="100%" frameborder="0" align="middle" height="100%" hspace="0" marginheight="0" marginwidth="0" scrolling="yes" style="background-color:#f7f7ff;"&gt;<br />&lt;/IFRAME&gt;</p>
		<p>　　或： <br />Href src=“<a href="http://localhost/names.nsf?Login&amp;Username=admin&amp;Password=password&amp;RedirectTo=/names.nsf" target="_parent">http:// </a><a href="http://host1/names.nsf?Login&amp;Username=admin&amp;Password=password&amp;RedirectTo=/names.nsf" target="_parent">host1</a><a href="http://localhost/names.nsf?Login&amp;Username=admin&amp;Password=password&amp;RedirectTo=/names.nsf" target="_parent">/names.nsf?Login&amp;Username=admin&amp;Password=pass&amp;RedirectTo=/names.nsf</a>” <br />以上采用的是在HTTP中直接传递明码，为提高安全性，可采用HTTPS来传递用户名和密码。另外采用这种方式被集成的系统必须支持FORM方式认证。J2EE应用，DOMINO等都支持FORM认证。</p>
		<p>　　这两种方式如果SSO成功，就自动进入目标系统的界面，如果实现会显示目标系统的登录界面。其效果图如下：</p>
		<p align="center">
				<img height="355" alt="登录界面" src="http://dev2dev.bea.com.cn/images/image060228004.jpg" width="552" />
		</p>
		<p>　　这种方式，必须维护对应关系表，如上面的sso_info。更好的方式是提供界面，让最终用户自己维护这种对应关系，可模仿Compoze portlets for lotus的做法，在用户第一次进入要与之做SSO的系统时，如DOMINO系统，显示一个界面，让用户自己输入他在该系统中的用户名/密码等信息。并保存到表中或LDAP等其他数据源中。以后用户要进入这些系统时，就直接从表中或其他数据源中取用户的用户名/密码等信息，帮助用户做认证。建议采用这种方式。如下图所示。如果用户改变了自己在DOMINO系统中的用户名，密码。从门户系统进入DOMINO系统时，认证会失败，就重新显示类似下面的界面。让用户重新输入他在DOMINO系统中新的用户名，密码并保存。</p>
		<p align="center">
				<img height="354" alt="认证失败" src="http://dev2dev.bea.com.cn/images/image060228006.jpg" width="575" />
		</p>
		<p>　　以上这种实现方式，一般需要浏览器支持COOKIE，所以要注意浏览器的配置，在开发阶段，为方便调试，可设置IE，让它显示COOKIE的名称。如下所示：</p>
		<p align="center">
				<img height="285" alt="浏览器的配置" src="http://dev2dev.bea.com.cn/images/image060228008.gif" width="553" border="0" />
		</p>
		<p>　　采用这种方式，对要集成的系统不需要做任何的改动。如果PORTAL系统中的用户在被集成的系统中的权限都一样，可采用建立一个通用用户的做法。也就是所有在PORTAL系统中的用户都采用这个通用用户进入目标系统。这种方式等于是采用页面集成方式做集成。比较方便使用。另外，有时候需要采用调用API，或配置Adapter等应用集成方式来集成其他系统，一般也是通过定义一个连接专用的用户。在API中或在配置Adapter的时候写死。如采用JAVA API方式集成DOMINO：</p>
		<p>　　<b>lotus.domino.Session dominoSession = NotesFactory.createSession(dominoServer, “admin”, “password”);</b></p>
		<h4>CS结构实现方式</h4>
		<p>　　经常有人问CS结构的应用如何实现SSO，本人的建议是对这种系统不要自己去实现SSO。很麻烦，其实输个用户名，密码没什么大不了的。如果要实现，一是采用商业软件。另外也可以采用以下方式：在PORTAL的PORTLET上建立超连接。并通过APPLET方式启动CS结构的应用系统的登录界面。然后通过如下的方式把用户名/密码传递过去。</p>
		<p>　　<b>-不能做任何改动的客户端</b> - WIN消息（给登录窗口发送用户名，密码等登录所需要的信息）,模拟键盘（java有模拟键盘输入的API）</p>
		<p>　　-<b>可以做改动的客户端</b> - 参数传递，并让登录的EXE文件读取参数进行认证。</p>
		<p>　　因为要让APPLET执行本地的EXE文件，所以必须对IE中的JRE的安全进行设置。</p>
		<p align="center">
				<img height="213" alt="对IE中的JRE的安全进行设置" src="http://dev2dev.bea.com.cn/images/image060228010.gif" width="554" border="0" />
		</p>
		<h4>其他：</h4>
		<p>　　在采用以上方式实现了SSO后，要注意LOGOUT，可采用与LOGIN相同的方式。也可以通过被集成系统的超时设置来实现。</p>
		<h4>单点登录SSO技术资料收集</h4>
		<ul>
				<li>
						<a href="http://www2.ccw.com.cn/05/0536/d/0536d06_2.asp/" target="_blank">统一用户认证和单点登录解决方案: </a> 计算机世界网上的文章,比较全面的介绍统一用户认证和单点登录解决方案 
</li>
				<li>
						<a href="http://www.ccw.com.cn/cio/solution/htm2005/20050829_102WJ.asp" target="_blank">惠普灵动单点登录(SSO)解决方案:</a>  包括C/S结构的系统单点登录解决方案 
</li>
				<li>
						<a href="http://www.ronghai.com/solution/2004-09/627/627_1.html" target="_blank">网站用户单点登录系统解决方案:</a>  通过令牌方式实现网站用户单点登录 
</li>
				<li>
						<a href="http://dev2dev.bea.com.cn/techdoc/200504501.html" target="_blank">WebLogic平台的Web SSO（SAML）解决方案:</a>  在WebLogic 8.1SP4中，提供了用于和Microsoft Windows客户端进行SSO的Single Pass Negotiate Identity Assertion Provider。本文对其做了详细的介绍。 
</li>
				<li>
						<a href="http://blog.beijingnet.com/index.php?blogId=4" target="_blank">http://blog.beijingnet.com/index.php?blogId=4:  </a>收录了一些SSO方面的文章 
</li>
				<li>
						<a href="http://www.ccw.com.cn/cio/research/info/htm2004/20041028_119LC.asp" target="_blank">应用整合中SSO的技术实现:  </a>作者介绍了南京地税进行应用整合SSO的技术实现方案 </li>
		</ul><img src ="http://www.blogjava.net/john_yu/aggbug/81408.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/john_yu/" target="_blank">john</a> 2006-11-16 00:23 <a href="http://www.blogjava.net/john_yu/archive/2006/11/16/81408.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UUID</title><link>http://www.blogjava.net/john_yu/archive/2006/11/16/81407.html</link><dc:creator>john</dc:creator><author>john</author><pubDate>Wed, 15 Nov 2006 16:18:00 GMT</pubDate><guid>http://www.blogjava.net/john_yu/archive/2006/11/16/81407.html</guid><wfw:comment>http://www.blogjava.net/john_yu/comments/81407.html</wfw:comment><comments>http://www.blogjava.net/john_yu/archive/2006/11/16/81407.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/john_yu/comments/commentRss/81407.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/john_yu/services/trackbacks/81407.html</trackback:ping><description><![CDATA[对UUID几乎没有了解，google了一下，才知道是128位整数(16字节)的全局唯一标识符(Universally Unique Identifier)。<br />UUID是指在一台机器上生成的数字，它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成UUID的API。UUID按照开放软件基金会(OSF)制定的标准计算，用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字。由以下几部分的组合：当前日期和时间(UUID的第一个部分与时间有关，如果你在生成一个UUID之后，过几秒又生成一个UUID，则第一个部分不同，其余相同)，时钟序列，全局唯一的IEEE机器识别号（如果有网卡，从网卡获得，没有网卡以其他方式获得），UUID的唯一缺陷在于生成的结果串会比较长。关于UUID这个标准使用最普遍的是微软的GUID(Globals Unique Identifiers)。<br />在ColdFusion中可以用CreateUUID()函数很简单的生成UUID，其格式为：xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16)，其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字。而标准的UUID格式为：xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)<br />，可以从<a href="http://www.cflib.org/">cflib</a> 下载<a href="http://www.cflib.org/udf.cfm?ID=54">CreateGUID() </a>UDF进行转换。<br />使用UUID的好处在分布式的软件系统中（比如：DCE/RPC, COM+,CORBA）就能体现出来，它能保证每个节点所生成的标识都不会重复，并且随着WEB服务等整合技术的发展，UUID的优势将更加明显。<br />关于UUID的更多信息可以多<a href="http://www.google.com/search?hl=zh-CN&amp;newwindow=1&amp;q=UUID&amp;btnG=%E6%90%9C%E7%B4%A2&amp;lr=">google</a> 一下。<br /><img src ="http://www.blogjava.net/john_yu/aggbug/81407.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/john_yu/" target="_blank">john</a> 2006-11-16 00:18 <a href="http://www.blogjava.net/john_yu/archive/2006/11/16/81407.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对String的深刻理解</title><link>http://www.blogjava.net/john_yu/archive/2006/02/07/29860.html</link><dc:creator>john</dc:creator><author>john</author><pubDate>Tue, 07 Feb 2006 14:29:00 GMT</pubDate><guid>http://www.blogjava.net/john_yu/archive/2006/02/07/29860.html</guid><wfw:comment>http://www.blogjava.net/john_yu/comments/29860.html</wfw:comment><comments>http://www.blogjava.net/john_yu/archive/2006/02/07/29860.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/john_yu/comments/commentRss/29860.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/john_yu/services/trackbacks/29860.html</trackback:ping><description><![CDATA[<DIV class=title>
<H2>对String的深刻理解</H2>
<P>刚开始玩java,对其String类，使用有些感触;</P>
<P>1、"abc"与new String("abc");<BR>&nbsp;&nbsp;&nbsp;&nbsp;经常会问到的面试题：String s = new String("abc");创建了几个String Object?【如这里创建了多少对象? 和一道小小的面试题 】<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;这个问题比较简单，涉及的知识点包括：<BR><BR>引用变量与对象的区别； <BR>字符串文字"abc"是一个String对象； <BR>文字池[pool of literal strings]和堆[heap]中的字符串对象。<BR>&nbsp;&nbsp;&nbsp;&nbsp;一、引用变量与对象：除了一些早期的Java书籍和现在的垃圾书籍，人们都可以从中比较清楚地学习到两者的区别。A aa;语句声明一个类A的引用变量aa[我常常称之为句柄]，而对象一般通过new创建。所以题目中s仅仅是一个引用变量，它不是对象。[ref 句柄、引用与对象]<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;二、Java中所有的字符串文字[字符串常量]都是一个String的对象。有人[特别是C程序员]在一些场合喜欢把字符串"当作/看成"字符数组，这也没有办法，因为字符串与字符数组存在一些内在的联系。事实上，它与字符数组是两种完全不同的对象。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Hello".length());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char[] cc={'H','i'};<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(cc.length);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;三、字符串对象的创建:由于字符串对象的大量使用[它是一个对象，一般而言对象总是在heap分配内存]，Java中为了节省内存空间和运行时间[如比较字符串时，==比equals()快]，在编译阶段就把所有的字符串文字放到一个文字池[pool of literal strings]中，而运行时文字池成为常量池的一部分。文字池的好处，就是该池中所有相同的字符串常量被合并，只占用一个空间。我们知道，对两个引用变量，使用==判断它们的值[引用]是否相等，即指向同一个对象：<BR><BR></P><PRE class=overflow>String s1 = "abc" ;<BR>String s2 = "abc" ;<BR>if( s1 == s2 ) <BR>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("s1,s2 refer to the same object");<BR>else&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("trouble");</PRE>
<P><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;这里的输出显示，两个字符串文字保存为一个对象。就是说，上面的代码只在pool中创建了一个String对象。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;现在看String s = new String("abc");语句，这里"abc"本身就是pool中的一个对象，而在运行时执行new String()时，将pool中的对象复制一份放到heap中，并且把heap中的这个对象的引用交给s持有。ok，这条语句就创建了2个String对象。<BR><BR></P><PRE class=overflow>String s1 = new String("abc") ;<BR>String s2 = new String("abc") ;<BR>if( s1 == s2 ){ //不会执行的语句}</PRE>
<P><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;这时用==判断就可知，虽然两个对象的"内容"相同[equals()判断]，但两个引用变量所持有的引用不同，<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;BTW：上面的代码创建了几个String Object? [三个，pool中一个，heap中2个。]<BR>&nbsp;&nbsp;&nbsp;&nbsp;[Java2 认证考试学习指南 (第4版)( 英文版)p197-199有图解。]<BR><BR><BR>2、字符串的+运算和字符串转换<BR>&nbsp;&nbsp;&nbsp;&nbsp;字符串转换和串接是很基础的内容，因此我以为这个问题简直就是送分题。事实上，我自己就答错了。<BR><BR>String str = new String("jf"); // jf是接分<BR>str = 1+2+str+3+4;<BR>一共创建了多少String的对象？[我开始的答案：5个。jf、new、3jf、3jf3、3jf34]<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;首先看JLS的有关论述：<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;一、字符串转换的环境[JLS 5.4 String Conversion]<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;字符串转换环境仅仅指使用双元的+运算符的情况，其中一个操作数是一个String对象。在这一特定情形下，另一操作数转换成String，表达式的结果是这两个String的串接。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;二、串接运算符[JLS 15.18.1 String Concatenation Operator + ]<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;如果一个操作数/表达式是String类型，则另一个操作数在运行时转换成一个String对象，并两者串接。此时，任何类型都可以转换成String。[这里，我漏掉了"3"和"4"]<BR><BR>如果是基本数据类型，则如同首先转换成其包装类对象，如int x视为转换成Integer(x)。 <BR>现在就全部统一到引用类型向String的转换了。这种转换如同[as if]调用该对象的无参数toString方法。[如果是null则转换成"null"]。因为toString方法在Object中定义，故所有的类都有该方法，而且Boolean, Character, Integer, Long, Float, Double, and String改写了该方法。 <BR>关于+是串接还是加法，由操作数决定。1+2+str+3+4 就很容易知道是"3jf34"。[BTW :在JLS的15.18.1.3中举的一个jocular little example，真的很无趣。]<BR>&nbsp;&nbsp;&nbsp;&nbsp;下面的例子测试了改写toString方法的情况.。<BR><BR></P><PRE class=overflow>class A{<BR>&nbsp;&nbsp;&nbsp;&nbsp;int i = 10;<BR>&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String []args){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String str = new String("jf");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str += new A();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(str);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;public String toString(){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return " a.i ="+i+"\n";<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}</PRE>
<P><BR><BR>三、字符串转换的优化<BR><BR>按照上述说法，str = 1+2+str+3+4;语句似乎应该就应该生成5个String对象：<BR><BR>1+2 ＝3，then 3→Integer(3)→"3" in pool? [假设如此] <BR>"3"+str(in heap) = "3jf"&nbsp;&nbsp;&nbsp;&nbsp; (in heap) <BR>"3jf" +3 ,first 3→Integer(3)→"3" in pool? [则不创建] then "3jf3" <BR>"3jf3"+4 create "4"&nbsp;&nbsp;in pool <BR>then "3jf34"<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;这里我并不清楚3、4转换成字符串后是否在池中，所以上述结果仍然是猜测。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;为了减少创建中间过渡性的字符串对象，提高反复进行串接运算时的性能，a Java compiler可以使用StringBuffer或者类似的技术，或者把转换与串接合并成一步。例如：对于 a + b + c ，Java编译器就可以将它视为[as if]<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;new StringBuffer().append(a).append(b).append(c).toString();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;注意，对于基本类型和引用类型，在append(a)过程中仍然要先将参数转换，从这个观点看，str = 1+2+str+3+4;创建的字符串可能是"3"、"4"和"3jf34"[以及一个StringBuffer对象]。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;现在我仍然不知道怎么回答str = 1+2+str+3+4;创建了多少String的对象，。或许，这个问题不需要过于研究，至少SCJP不会考它。<BR><BR>3、这又不同：str = "3"+"jf"+"3"+"4";<BR>&nbsp;&nbsp;&nbsp;&nbsp;如果是一个完全由字符串文字组成的表达式，则在编译时，已经被优化而不会在运行时创建中间字符串。测试代码如下：<BR><BR></P><PRE class=overflow>String str1 ="3jf34";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String str2 ="3"+"jf"+"3"+"4"; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(str1 == str2) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("str1 == str2");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("think again");<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(str2.equals(str1))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("yet str2.equals(str1)");</PRE>
<P><BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;可见，str1与str2指向同一个对象，这个对象在pool中。所有遵循Java Language Spec的编译器都必须在编译时对constant expressions 进行简化。JLS规定：Strings computed by constant expressions (&amp;yacute;15.28) are computed at compile time and then treated as if they were literals. <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;对于String str2 ="3"+"jf"+"3"+"4";我们说仅仅创建一个对象。注意，“创建多少对象”的讨论是说运行时创建多少对象。<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;BTW：编译时优化<BR><BR></P><PRE class=overflow>&nbsp;&nbsp;&nbsp;&nbsp;String x = "aaa " + "bbb ";<BR>&nbsp;&nbsp;&nbsp;&nbsp;if (false) {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x = x + "ccc ";<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;x +=&nbsp;&nbsp;"ddd ";<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;等价于：<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;String x = "aaa bbb ";<BR>&nbsp;&nbsp;&nbsp;&nbsp;x = x + "ddd ";</PRE>
<P><BR><BR>4、不变类<BR>&nbsp;&nbsp;&nbsp;&nbsp;String对象是不可改变的(immutable)。有人对str = 1+2+str+3+4;语句提出疑问,怎么str的内容可以改变？其实仍然是因为不清楚：引用变量与对象的区别。str仅仅是引用变量，它的值——它持有的引用可以改变。你不停地创建新对象，我就不断地改变指向。[参考TIJ的Read-only classes。]<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;不变类的关键是，对于对象的所有操作都不可能改变原来的对象[只要需要，就返回一个改变了的新对象]。这就保证了对象不可改变。为什么要将一个类设计成不变类？有一个OOD设计的原则：Law of Demeter。其广义解读是：<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;使用不变类。只要有可能，类应当设计为不变类。<BR></P></DIV><img src ="http://www.blogjava.net/john_yu/aggbug/29860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/john_yu/" target="_blank">john</a> 2006-02-07 22:29 <a href="http://www.blogjava.net/john_yu/archive/2006/02/07/29860.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat 配置</title><link>http://www.blogjava.net/john_yu/archive/2006/01/02/26386.html</link><dc:creator>john</dc:creator><author>john</author><pubDate>Mon, 02 Jan 2006 14:36:00 GMT</pubDate><guid>http://www.blogjava.net/john_yu/archive/2006/01/02/26386.html</guid><wfw:comment>http://www.blogjava.net/john_yu/comments/26386.html</wfw:comment><comments>http://www.blogjava.net/john_yu/archive/2006/01/02/26386.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/john_yu/comments/commentRss/26386.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/john_yu/services/trackbacks/26386.html</trackback:ping><description><![CDATA[<DIV class=postTitle>&nbsp;</DIV>
<P><STRONG>1、tomcat下配置虚拟目录<BR></STRONG><BR>&nbsp;&nbsp;&nbsp;打开TOMCAT文件下的conf\server.xml文件&nbsp;，查找到&lt;ContextManager&gt;标签，并在该标签的结束标签&lt;/ContextManager&gt;前面加上：<BR><BR>&nbsp;&nbsp;&nbsp;&lt;Context path="虚拟目录" docBase="硬盘目录" debug="0" reloadable="true" crossContext="true"/&gt;&nbsp;&nbsp;<BR><BR>&nbsp;&nbsp;&nbsp;<STRONG>其中path的值是虚拟目录，docbase的值是你的硬盘的的目录的绝对路径。</STRONG><BR><BR>&nbsp;&nbsp;&nbsp;如找不到&lt;ContextManager&gt;元素，可以找<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Host name="localhost" debug="0" appBase="webapps"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unpackWARs="true" autoDeploy="true"<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlValidation="false" xmlNamespaceAware="false"&gt; </P>
<P>&nbsp;&nbsp;&nbsp;然后添加&lt;Context path="虚拟目录" docBase="硬盘目录" debug="0" reloadable="true" crossContext="true"/&gt;&nbsp;&nbsp;<BR><BR><STRONG>2、禁止tomcat目录浏览,将listings设为false</STRONG></P>
<P><STRONG>&nbsp;&nbsp;&nbsp; </STRONG>&lt;servlet&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;default&lt;/servlet-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.catalina.servlets.DefaultServlet<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/servlet-class&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;debug&lt;/param-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;0&lt;/param-value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;listings&lt;/param-name&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;false&lt;/param-value&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<BR>&nbsp;&nbsp;&nbsp; &lt;/servlet&gt; </P>
<P><STRONG>3、设置友好错误页面，配置web.xml</STRONG></P>
<P>&nbsp;&nbsp; &lt;error-page&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;error-code&gt;404&lt;/error-code&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;location&gt;/error.jsp&lt;/location&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;/error-page&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;error-page&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;error-code&gt;500&lt;/error-code&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;location&gt;/error.jsp&lt;/location&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;/error-page&gt;<BR><BR><STRONG>4、在IE中直接打开其他扩展名的文件<BR></STRONG><BR>&nbsp;&nbsp;&nbsp;为了让能在IE浏览器中自动打开其他扩展文件名的文件的设置：<BR>&nbsp;&nbsp;&nbsp;需要在WEB.XML中进行如下的设置：<BR>&nbsp;&nbsp;&nbsp;在WEB.XML中添加&lt;mime-mapping&gt;,其中:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>&lt;extension&gt;: 文件的扩展名&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mime-type&gt;: 除了该类型文件的可执行文件,同WINDOW注册表中的&nbsp;</STRONG>&nbsp;<STRONG>/HKEY_CLASSES_ROOT下该类文件的Content Type 的值一样.</STRONG> <BR><BR>如能在IE中自动打开DOC，XLS，PDF文件的配置如下: </P>
<P>&lt;?xml version="1.0" ?&gt; <BR>&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 1.2//EN"&nbsp; "<A href="http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">http://java.sun.com/j2ee/dtds/web-app_2_2.dtd</A>"&gt; <BR>&lt;web-app&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;mime-mapping&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;extension&gt;doc&lt;/extension&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mime-type&gt;application/msword&lt;/mime-type&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;/mime-mapping&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&lt;mime-mapping&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;extension&gt;xls&lt;/extension&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mime-type&gt;application/msexcel&lt;/mime-type&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;/mime-mapping&gt;<BR><BR>&nbsp;&nbsp;&nbsp;&lt;mime-mapping&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;extension&gt;pdf&lt;/extension&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mime-type&gt;application/pdf&lt;/mime-type&gt;<BR>&nbsp;&nbsp;&nbsp;&lt;/mime-mapping&gt;<BR>&lt;/web-app&gt; </P><img src ="http://www.blogjava.net/john_yu/aggbug/26386.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/john_yu/" target="_blank">john</a> 2006-01-02 22:36 <a href="http://www.blogjava.net/john_yu/archive/2006/01/02/26386.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>