﻿<?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-josson.jin</title><link>http://www.blogjava.net/josson/</link><description>天地生人,有一人应有一人之业;人生在世,生一日当尽一日之勤!</description><language>zh-cn</language><lastBuildDate>Wed, 29 Apr 2026 02:12:20 GMT</lastBuildDate><pubDate>Wed, 29 Apr 2026 02:12:20 GMT</pubDate><ttl>60</ttl><item><title>基于客户端（浏览器）证书身份认证的方法</title><link>http://www.blogjava.net/josson/archive/2011/12/09/365966.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Fri, 09 Dec 2011 08:09:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2011/12/09/365966.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/365966.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2011/12/09/365966.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/365966.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/365966.html</trackback:ping><description><![CDATA[1、介绍<br /><div><div>通过证书验证用户身份（浏览器），其核心是利用cookie实现http和https的信息共享（同域名）。如http://test.abc.com/app/index.html 发现未验证后，跳转到https://test.abc.com:443/app/checkCrt.html身份验证，要求出去证书，确认后将身份信息带入http请求头部，跳转到原请求页面（http://test.abc.com/app/index.html ），读取身份信息后进入页面(出于安全考虑Cookie需要加密)。</div></div><br />流程图<br /><img src="http://www.blogjava.net/images/blogjava_net/josson/certauth.png" border="0" alt="" width="666" height="589" data-pinit="registered" /><br />流程说明：<br /><div><div>登录流程详细介绍：</div><div>1）. 未登录用户访问页面 如：http://test.abc.com/app/index.html</div><div>2）. 【CertAuthValve】判断是否访问受限制资源，如访问受限制的资源则判断用户身份是否已验证，未验证则将用户重定向到身份验证页面，原始请求的url做为</div><div>query的一部分，登录成功后可以跳转回来， 如：https://test.abc.com:443/app/checkCrt.htm?done=/index.html。</div><div>3）. 【CertAuthValve】对于https请求，apache读取请求提供的用户证书，获取证书中的邮件地址，并将该信息写入请求头中。</div><div>4）. 【GetUserInfoValve】读取请求头，获取刚刚设置的用户邮件地址信息，进一步获取用户的详细信息，然后将这些信息加密后放入cookie中。</div><div>5）. 登录完成，将用户外部重定向回原始页面。</div></div>2、具体实现<br />1）、安装apache、ssh、java、jboss等环境，略。<br />2）、生成服务证书和服务密码<div><div><div style="font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; background-color: #eeeeee; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->openssl&nbsp;req&nbsp;-<span style="color: #0000FF; ">new</span>&nbsp;-x509&nbsp;-nodes&nbsp;-out&nbsp;/home/admin/app/conf/ssl.crt/server.crt&nbsp;-keyout&nbsp;/home/admin/app/conf/ssl.crt/server.key&nbsp;-days&nbsp;3600</div></div><div>因为要和内网证书交互，所以需要一个内网证书公钥文件，可以通过以下方式获取:</div><div>获取方法：IE-&gt;工具-&gt;Internet选项-&gt;内容-&gt;证书-&gt;受信任的根证书颁发机构，找到intranet行，点击导出，选择下一步，选择Base64编码X.509,将证书文件保存为intranet-ca.crt，拷贝到目录/home/admin/app/conf/ssl.crt/。<br />3）、apache(httpd.conf)配置</div></div>应用和身份验证页面放在一起，所以需要同时配置两个虚拟主机，同时监听80（处理http请求）、443（处理https请求）端口。<br /><div style="border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; background-color: #eeeeee; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><font class="Apple-style-span" size="2">#监听端口</font><br /><font class="Apple-style-span" size="2">Listen&nbsp;80</font><br /><font class="Apple-style-span" size="2">Listen&nbsp;443</font><br /><br /><font class="Apple-style-span" size="2">#app的虚拟主机配置</font><br /><div><div style="font-size: 13px; ">NameVirtualHost *:80</div><div style="font-size: 13px; ">&lt;VirtualHost *:80&gt;</div><div style="font-size: 13px; ">&nbsp; &nbsp; ServerAdmin sa@abc.com</div><div style="font-size: 13px; ">&nbsp; &nbsp; ServerName test.abc.com</div><div style="font-size: 13px; ">&nbsp; &nbsp; DocumentRoot /home/admin/app/target/app/htdocs/</div><div><font class="Apple-style-span" size="2">&lt;/VirtualHost&gt;</font><br /><br /><font class="Apple-style-span" size="2">#身份验证的虚拟主机配置</font><br /><div><div>NameVirtualHost *:443</div><div>&lt;VirtualHost *:443&gt;</div><div>&nbsp; &nbsp; ServerAdmin sa@abc.com</div><div>&nbsp; &nbsp; ServerName test.abc.com</div><div>&nbsp; &nbsp; DocumentRoot&nbsp;<span class="Apple-style-span" style="font-size: 13px; ">/home/admin/app/target/app/htdocs/</span></div><div></div><div>&nbsp; &nbsp; SSLEngine on</div><div>&nbsp; &nbsp; SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+SSLv3:+EXP:+eNULL<br /><br /><div>&nbsp; &nbsp;&nbsp;#该指令为虚拟主机指定证书文件名。</div></div><div>&nbsp; &nbsp; SSLCertificateFile /home/<span style="font-size: 13px; ">admin</span><span style="font-size: 13px; ">/</span><span style="font-size: 13px; ">app</span><span style="font-size: 13px; ">/</span><span style="font-size: 13px; ">conf</span><span style="font-size: 13px; ">/</span>ssl.crt/server.crt<br /><br /><div>&nbsp; &nbsp; #该指令为证书指定一个对应的私钥文件</div></div><div>&nbsp; &nbsp; SSLCertificateKeyFile /home<span style="font-size: 13px; ">/</span><span style="font-size: 13px; ">admin</span><span style="font-size: 13px; ">/</span><span style="font-size: 13px; ">app</span><span style="font-size: 13px; ">/</span><span style="font-size: 13px; ">conf</span><span style="font-size: 13px; ">/</span>ssl.crt/server.key<br /><br /><div>&nbsp; &nbsp; #该指令为指定一个包含Certificate Authority证书的文件<br /><div><div>&nbsp; &nbsp; #证书公钥</div></div></div></div><div>&nbsp; &nbsp; SSLCACertificateFile /home<span style="font-size: 13px; ">/</span><span style="font-size: 13px; ">admin</span><span style="font-size: 13px; ">/</span><span style="font-size: 13px; ">app</span><span style="font-size: 13px; ">/</span><span style="font-size: 13px; ">conf</span><span style="font-size: 13px; ">/</span>ssl.crt/intranet-ca.cer</div><div></div><div>&nbsp; &nbsp; SSLProxyEngine on</div><div>&nbsp; &nbsp; RewriteEngine on</div><div>&nbsp; &nbsp;&nbsp;#设置客户端证书验证为必须</div><div>&nbsp; &nbsp; SSLVerifyClient require<br /><br /><div><div>&nbsp; &nbsp; #因为一个CA证书能够被另一个CA证书验证，所以可以形成一个CA证书链.使用该指令可指定服务器验证用户证书时可以查找多少个CA证明。</div><div>&nbsp; &nbsp; #设置认证深度：一般用默认10。</div></div></div><div>&nbsp; &nbsp; SSLVerifyDepth &nbsp;10<br /><br />&nbsp; &nbsp;&nbsp;#把mod_ssl里的变量变为全局环境的变量</div><div>&nbsp; &nbsp; SSLOptions +StdEnvVars<br /><br /><div><div>&nbsp; &nbsp; #将证书中的邮件地址添加到请求头中</div></div></div><div>&nbsp; &nbsp; RequestHeader unset SSL_CLIENT_S_DN_Email</div><div>&nbsp; &nbsp; RequestHeader add SSL_CLIENT_S_DN_Email %{SSL_CLIENT_S_DN_Email}e</div><div>&lt;/VirtualHost&gt;</div></div></div></div></div><br />4)、代码片段<br /><div style="font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; background-color: #eeeeee; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//</span><span style="color: #008000; ">CertAuthValve.java<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">判断session中是否有用户邮箱地址</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SessionValue&nbsp;session&nbsp;=&nbsp;SessionHelper.getSessionValue(rundata);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(StringUtil.isNotEmpty(session.getCropEmail()))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;从内网证书中获取用户邮箱地址:&nbsp;</span>SSL_CLIENT_S_DN_Email<span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;cropEmail&nbsp;=&nbsp;rundata.getRequest().getHeader(SSL_CLIENT_HEADER_MAIL);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(StringUtil.isNotEmpty(cropEmail))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">将邮箱地址保存到session</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.setCropEmail(cropEmail);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SessionHelper.saveSessionValue(rundata,&nbsp;session);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(log.isDebugEnabled())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.debug("用户"&nbsp;+&nbsp;session.getCropEmail()&nbsp;+&nbsp;"已经通过证书验证");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URIBrokerService&nbsp;uriBrokerService&nbsp;=&nbsp;(URIBrokerService)&nbsp;getWebxComponent().getService(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URIBrokerService.SERVICE_NAME);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URIBroker&nbsp;noPermissionUriBroker&nbsp;=&nbsp;uriBrokerService.getURIBroker(CHECK_CRT_URL);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">请求的原始URL&nbsp;&amp;&nbsp;验证的URL</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;requestPath&nbsp;=&nbsp;rundata.getPathInfo().replace("_",&nbsp;"");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;checkCrtUrl&nbsp;=&nbsp;(String)&nbsp;noPermissionUriBroker.getPath().get(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;noPermissionUriBroker.getPath().size()&nbsp;-&nbsp;1);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">原始请求判断</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(requestPath.equalsIgnoreCase(checkCrtUrl))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">当前是https请求，但是依然不能得到证书信息,转到禁止页面<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">(要将禁止页面加入到允许访问的配置文件中，不然会导致循环重定向)</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URIBroker&nbsp;uriBroker&nbsp;=&nbsp;uriBrokerService.getURIBroker("forbidden");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rundata.setRedirectLocation(uriBroker.render());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">转到证书验证页面</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rundata.setRedirectLocation(noPermissionUriBroker.render()&nbsp;+&nbsp;"?done="&nbsp;+&nbsp;rundata.getPathInfo());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">catch</span>&nbsp;(IOException&nbsp;e)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;log.error("权限验证重定向出错",&nbsp;e);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;BreakPipeline();</div><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//</span><span style="color: #008000; ">GetUserInfoValve.java</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;user&nbsp;=&nbsp;rundata.getSession().getAttribute("userInfo");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(user&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SessionValue&nbsp;session&nbsp;=&nbsp;SessionHelper.getSessionValue(rundata);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;email&nbsp;=&nbsp;session.getCropEmail();<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Employe&nbsp;employe&nbsp;=&nbsp;PersonInfoUtil.getPersonInfoByEmail(email);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;写入cookie</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.setEmployeeId(employe.getEmployeId());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.setName(employe.getName());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.setCropEmail(employe.getEmail());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SessionHelper.saveSessionValue(rundata,&nbsp;session);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><br /> <pinit id="__huaban_Button" style="display: none; ">采集到花瓣</pinit><img src ="http://www.blogjava.net/josson/aggbug/365966.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2011-12-09 16:09 <a href="http://www.blogjava.net/josson/archive/2011/12/09/365966.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>firefox中证书的使用</title><link>http://www.blogjava.net/josson/archive/2011/12/09/365953.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Fri, 09 Dec 2011 05:54:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2011/12/09/365953.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/365953.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2011/12/09/365953.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/365953.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/365953.html</trackback:ping><description><![CDATA[受限于证书的原因，以前经常不得已用IE打开一些应用。其实有一工具可以帮助我们导出IE证书，用于firefox，解决证书的困惑。<br /><br /><div>Jailbreak [<a href="https://www.isecpartners.com/application-security-tools/jailbreak.html">https://www.isecpartners.com/application-security-tools/jailbreak.html</a>]，win32的一个小软件，可以帮助我们导出IE证书，使用很简单。<br />1、windows环境（xp\win7均可），以adminstrator登录；<br />2、下载jailbreak，解包后，运行jailbreak.exe（非jailbreak.msc）；<br />3、导出证书：Certificates - Current User &gt; 个人 &gt; 证书，选所有任务导出；<br /><div><div><img src="http://www.blogjava.net/images/blogjava_net/josson/jailbreak.jpg" border="0" alt="" width="871" height="499" data-pinit="registered" /><br /><br />选择导出私钥。<br /><img src="http://www.blogjava.net/images/blogjava_net/josson/xxx.jpg" border="0" alt="" width="513" height="432" data-pinit="registered" /></div></div>4、在firefox中导入证书：选项 &gt; 高级 &gt; 查看证书（您的证书） &gt; 导入(刚导出证书文件)；<br /><img src="http://www.blogjava.net/images/blogjava_net/josson/zzz.jpg" border="0" alt="" width="607" height="422" data-pinit="registered" /><br />5、搞定。</div> <pinit id="__huaban_Button" style="display: none; ">采集到花瓣</pinit><img src ="http://www.blogjava.net/josson/aggbug/365953.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2011-12-09 13:54 <a href="http://www.blogjava.net/josson/archive/2011/12/09/365953.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于互联网产品开发最佳实践探讨</title><link>http://www.blogjava.net/josson/archive/2011/06/13/351998.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Mon, 13 Jun 2011 07:53:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2011/06/13/351998.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/351998.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2011/06/13/351998.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/351998.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/351998.html</trackback:ping><description><![CDATA[<div>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">互联网的产品大都是面向海量用户的服务，且用户分布区域广泛，其教育水平、习惯也大多不同，具有高度不确定性，我们必须非常关注用户的行为和反馈。因而，在互联网产品服务的整个用户研究，需求分析、产品研发及交付服务的过程中，都采用探索式、适应性的研发理念进行产品的研发。通常，会把整个产品研发周期划分为若干个迭代，采用迭代式的演进过程，不断的去交付新的产品特性，并通过观察用户的行为和反馈获取，进而随时调整产品的思路和方向。一切以用户价值为核心是互联网产品最核心的特点，而以价值驱动的敏捷开发方法非常符合这一特点。</span></p><span style="font-size: 9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">一、敏捷项目管理实践</span>  <p style="text-align:left" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black"><img alt="" src="http://www.blogjava.net/images/blogjava_net/josson/agile.png" width="520" height="280" /><br /></span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">从阿里软件开始，内贸团队就一直在实行着敏捷项目管理实践，</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">通过小步快跑，快速迭代、增量交付用户价值，不断获取用户反馈，持续、快速的调整产品，验证并适合用户价值。正是通过这些实践活动，我们以迭代的、增量的交付用户价值，最大限度的保证产品朝着符合用户实际需求方向发展。目前，在内贸团队应用较成熟的敏捷实践活动有：</span></p>  <p style="text-align:left" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">1)</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">、迭代计划(Sprint Planning Meeting)</span></p>  <p style="text-align:left" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">2)</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">、每日晨会(Daily Scrum Meeting) &amp; 任务墙(Task Wall)</span></p>  <p style="text-align:left" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">3)</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">、功能预演(Spring Review)</span></p>  <p style="text-align:left" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">4)</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">、项目总结(Retrospect Meeting)</span></p>  <p style="text-align:left" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">5)</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">、结对编程(Pair Programming)</span></p>  <p style="text-align:left" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">6)</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">、其他技术实践活动等</span></p>  <p style="text-align:left" align="left">&nbsp;<span style="font-size: 9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">二、敏捷团队</span></p>  <p style="text-align:left" align="left"><span style="font-size: 9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">１)、自组织文化</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">如google、facebook等互联网企业，他们很少甚至没有特定的项目流程，通常怎么敏捷怎么做，具有浓厚的工程师驱动文化。我们则有较完整的开发流程指导和规范我们的项目研发工作，相比而言，丧失了一些灵活性和积极性，不利于我们工程师自我管理、自我驱动意识的培养。臃肿、缺乏灵活性的流程同互联网产品快速更新、快速发展是不相适应的，同时也弱化我们的责任心意识。除了遵守详尽的流程，我们是否可以换个角度、换种方法，提倡和营造一种自我管理、自我驱动的开发文化，省却一些并不能给我们带来帮助却影响效率的流程呢？</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black">敏捷团队的自组织特性弱化了团队技术领导这个角色，强调自我管理和自我驱动。</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">虽然这对工程师的素质要求更高，相对技术能力更难提高。但是，团队导向很重要，我们努力营造这样的氛围，从小团队做起，逐渐锻炼和培养自组织团队。相信在这样的开发氛围下，会让我们做的更高效、更敏捷，可以走的更稳、更远。</span></p>  <p style="text-align:left" align="left"><span style="font-size: 9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">２）、追求一体化</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">一体化团队作为敏捷开发方法中最具精益思想基因的实践，是指每个项目团队包括分析，开发，测试等角色，使团队满足一个需求从设计，开发到测试各个阶段顺利完成，达到符合质量标准并满足需求的软件。这种以项目/产品为单位的虚拟团队，坐在一起，全身心的为共同的目标而努力，可以更好的凝聚项目组中的各种角色，消除部门墙。&nbsp;</span></p>  <p style="text-align:left" align="left">&nbsp;<span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">3</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">）、追求全功能</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">这里所指的全功能是希望项目团队能打破工程师角色之间的边界，如研发、测试和前端工程师的界线，消除开发、测试流程中一些潜在浪费，提高效率。在项目团队内部通过角色互换，不限角色的结对工作，加强不同角色，不同模块间的知识传递，打破技术壁垒，帮助员工从不同视角理解项目，锻炼技能，进而增加团队均衡生产的能力。</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">为什么要提倡打破边界？项目整体效率依赖于项目过程中各环节的工作效率，而整体效率的优化往往依赖于均衡生产(精益思想的按需生产)，即消除生产的波峰(过度生产)和波谷(生产不足)，只有局部效率的增加无法直接转换为整体效率的增加(就象桶能装多少水，决定于最短的那块板)。整体效率的优化要求IT团队消除技能壁垒，培养多面手，根据计划的的变动，弹性地调整任务，达到各角色和流程之间的平衡。</span></p>    <p style="text-align:left" align="left"><span style="font-size: 9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">三、质量保证</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">我们追求开发效率，同时也注重项目质量。如何去保证质量？就象美国的一位教授爱德化.戴明（W.Edwards Deming）所说：&#8220;我们应该停止依靠大量检验来保证质量，而是要改进工艺流程，从一开始就生产出优质的产品&#8221;。我们要在整个开发过程中多个环节去保证质量。同时，质量保证是整个团队的责任，就如同前面所说的追求全功能团队，打破边界。</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">至于在哪些环节采用哪些实践，我们先做个分类，按是否能被系统用户感知将质量问题区分内部质量和外部质量。外部质量指能直接被系统用户感知，如运行缓慢，不可操作或是操作复杂就属于外部质量低劣。而不能直接为系统用户所直接感知的要素，对产品键壮性、可维护性有深远影响的问题就属于外部质量，如系统设计的一致性、代码可读性、逻辑完整性等。内部质量对用户的影响比较间接，但比外部质量意义更深远。一般来说，系统内部质量优秀，外部质量仍有可能很差。而内部质量差的系统，外部质量肯定也不怎么样。</span></p>  <p style="text-align:left" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">1</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">）、外部质量保证</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">在外部质量保证上，大部分会在开发后期介入，可以通过性能测试、自动化测试及工程师的功能测试来保证，通过这些实践活动发现并保证例如运行缓慢、不可操作等质量问题不会存在。针对交互特别复杂的web应用，可以更多的考虑采用webui自动化测试工具，如selenium、pwaitr(b2b)、automan(淘宝)等，可以很好的完成那些简单、重复的TC用例，可以大大提高测试效率，解决测试工程师的资源瓶颈。</span></p>  <p style="text-align:left" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">2)</span><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">、内部质量保证</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">相对于外部质量，内部质量问题影响更为深远，在开发开始阶段就应该去保证。如通过单元测试、静态代码扫描(PMD\findbugs)、持续集成、重构、结对编程、code review等多种实践活动来保证项目代码的健康。</span></p>  <p style="text-align:left;text-indent:18.0pt" align="left"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">除了一些实践活动去检查代码质量外，更为重要的是研发工程师对内部质量的重视，如果工程师没有形成良好的质量意识，很可能这些实践也只是停留于形式，并不能带来较好的结果。如我们在开发过程中的编码规范、单元测试的质量及覆盖率，code review的及时性及问题是否持续跟进等等。此外，有选择的采用结对编程实践，有助于质量的提高。</span></p>      <span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:black;">本文以敏捷、精益（消除浪费、按需生产）思想的角度</span><span style="font-size: 9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">试图<span style="color:black">去探讨一种适合互联网公司的产品开发体系，上述概要的介绍了项目管理、团队、质量方面的一些敏捷实践活动，主要涉及了我们对敏捷方面的经验分享或者是些正在研究探讨的课题。</span>文中涉及的实践活动，后续我将逐一展开详细介绍，帮助大家更好的理解和认识。希望本文的分享能成为一个引子，引起大家对敏捷开发的思考和讨论，或者更好的了解敏捷和精益思想。 </span></div><img src ="http://www.blogjava.net/josson/aggbug/351998.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2011-06-13 15:53 <a href="http://www.blogjava.net/josson/archive/2011/06/13/351998.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈项目管理中质量及效率</title><link>http://www.blogjava.net/josson/archive/2011/05/20/350701.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Fri, 20 May 2011 08:39:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2011/05/20/350701.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/350701.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2011/05/20/350701.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/350701.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/350701.html</trackback:ping><description><![CDATA[<div>  <p style="margin-left: 18pt; text-indent: -18pt;"><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;; color: #1f497d;">以下为本人在公司内部关于项目质量和工作效率邮件回复的一此意见和想法。<br /></span></p><p style="margin-left:18.0pt;text-indent:-18.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">1、 </span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">谈流程</span></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">不可否认流程的重要性，但<strong>我们需要根据具合格情况分析，不断的梳理和优化我们的流程，让流程更好的指导我们工作，而不是束缚。</strong>目前，我们的流程慢慢多了起来，感觉不如以前敏捷了。经过rpm改造后，无论在测试环节还是发布阶段，较之前失去了很大的灵活性。测试阶段，开发bugfix后想在测试环境验证，每次必须重走aone的流程及打包布署，相比之前的build效率真的差了好多。当然，也许是我们项目组对这个流程熟练度、方法还不够，很多环节有待改进。</span></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">发布阶段，目前统一由SCM来发布，必然会导致开发对线上环境及发流程更加陌生，同我们提倡的打破边界，敏捷响应有些相背。再者，SCM资源有限的原因，要支持ITU众多产品线，能否应付的过来，始终是个问题。发布统一管理有好处，同样也带来了弊端，ITU不同于网站，大多数的技术团队共同在维护在几个应用，而itu的应用多、规模相对小、环境各异，这样的产品线采用统一管理性价比不高。<strong>希望相应的owner，能不定期的搜集各产品线的意见和反馈，不断的优化，让我们的流程更合理。</strong></span></p>    <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">2、 </span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">谈自测</span></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">我们团队一直在强调自测意识，也在这方面不断的总结和改进。我觉的要提高自测，<strong>首先应让每位开发同学形成较好的自测意识</strong>，而不是自上而下的命令式管理，只有自己有这方面的意，才会去思考、去想办法，去实践。<strong>再者，需要PM或技术经理去思考，目前阶段实行自测会有什么困难</strong>，如没有系统的自测方法、时间不充足（需要熟悉下阶段的UC、下迭代的设计、单元测试补写等），找到这些困难或问题，就容易对症下药了。<strong>最后，不断总结和积累自测方式，优化项目流程。</strong>自测不是一种形式，而要追求效果，开发自测同样需要计划和方法，所以我们需要向QA同学请教，总结过去 bug常犯的错误，整理自己的check项。相信通过这样的一些自测方法，能真正提高我们的项目质量，打破同QA的界线，我们的开发、测试资源比例可以得到更大的优化，将以前开发阶段紧，测试阶段松的状况加以改善，使整个项目过程中的紧张度趋于平缓。</span></p>    <p style="margin-left:18.0pt;text-indent:-18.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">3、 </span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">谈故障分</span></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">&#8220;尽量不要让故障分成为大家包袱，可以考虑被实施产品对事故级和A类才对个人计故障分，B和C类故障分记在主管头上！&#8221;，个人也比较支持骆驼的观点。目前大家对线上故障都小心翼翼，大家对质量的意识很高，这当然是好事，但同时带来的影响是效率低了。我的观点是，作为增值服务的互联网产品，我们更需要快速迭代增量提供用户价值，尽快获取用户反馈并改善产品，产品推出的迟早，不仅影响获得回报的时间，还影响到获得价值的多少，错过了一个时间窗口，产品可能就不再有任何价值。所以，<strong>我们需要找到一个平衡量点，可接受的质量状况达到最大的效率。</strong></span></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">从客户第一角度谈质量，某些时候，客户可以接受服务偶而不可用重启下，却不能接受产品没价值、交互性太差，操作太复杂。所以，对于客户来说什么对他们更重要，就需要我们每个人去分析和评估。所以，我们一味只注重质量，而忽略客户真实需求，那就太悲哀。<strong>我的观点是，case by case，带着这样的观点去思考和解决问题。</strong></span></p>    <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;; color:#1F497D">4</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">、谈敏捷项目团队</span></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:#1F497D">从打破边界，我想到了一体化的敏捷项目管理团队，<strong>一个目标一致、自我管理的团队，应该具备良好的目标意识和执行力，不仅能管好自己的一亩三分地，同时也能站在项目、团队的角度看待问题。</strong>PD出现了问题，开发积极去弥补；开发出现了问题，QA积极去弥补，项目团队的目标非常一致。每位项目组成员一定要把好每一关，万不可把问题向下抛，因为还有开发或QA会把关，所以差不多就行了，这样往往就是灾难的开始。</span></p>  </div><img src ="http://www.blogjava.net/josson/aggbug/350701.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2011-05-20 16:39 <a href="http://www.blogjava.net/josson/archive/2011/05/20/350701.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我的2010</title><link>http://www.blogjava.net/josson/archive/2011/02/02/342882.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Wed, 02 Feb 2011 13:46:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2011/02/02/342882.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/342882.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2011/02/02/342882.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/342882.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/342882.html</trackback:ping><description><![CDATA[2010已成为历史，记忆里2010年变化很多、做的很多、收获也很多。2010是个转型期、创业期，从年初开始，就在新的Marking中努力耕耘。前半年，以新产品研发为主；后半年，结合客户使用产品后的反馈，不断的优化和改进产品功能，努力提升产品价值和用户体验。通过大家的努力，几款新产品还是彼受用户欢迎的，最欣喜的是我们提前完成了2010年的KPI目标。<br />
<br />
过去的一年，有着太多的痛苦和艰辛，为了新产品的上线，晚上、周未都没了，唯一想的和做的就是确保产品如期上线。过程虽然很艰苦，但大家都努力坚持，齐心协力，确保任务如期完成，我们保持了一贯的说到做到、如期交付的作风。因为这样的磨练，我和我们的团队得到了更多成长。困难并不可怕，熬过去，明天的太阳会更加灿烂。<br />
<strong><br />
1、谈谈成长和不足：</strong><br />
1）、职业转型，开发到管理<br />
虽然Team Leader已经做了几年了，但一直停留在项目上，多为管事不管人，对细节问题关注较多，所以之前谈不上管理，只能算是积累些项目管理经验。经过这一年的学习和发展，有了更多的管理意识，逐渐关注团队建设、团队成长，注意给小组成员更多的机会和空间，让他们得到锻炼和成长，承担更多团队或项目中的重要事项，而他们通过完成这些重要任务，不仅得到了磨练，同时在团队中建立了自己的影响力。<br />
放在以前，我会认为有风险，或者自己做更快，更省事，或最有把握的人去。现在想来，以前认识太肤浅了，我们需要的团队战斗力，而不是个别人的能力，若平常不注重团队成员的培养，团队的战斗力永远不行，承担不了关键任务。<br />
谈到成长和培养，团队需要什么样的人呢？作为互联网企业，同一般软件企业不同，产品在推出之前，谁也无法肯定是否会受用户欢迎，只能快速推出，让市场来验证，不断的改进和适应用户的需要。因而，需要我们技术人员也具备技术判断力，改变命令式管理体制下的工作习惯，充分发挥主观能动性和创新意识，共同做好产品。<br />
<br />
2）、学会拥抱变化；<br />
2010年变化很多，有些也许对个人、团队没有影响或影响很小，有些直接关系自己或团队，如团队的核心成员不断的被抽调、人员调整、KPI的271考评等，每次的变化都会带来不同的问题。持续输血，新人补允，使团队战斗力大打折扣，很长一段时间非常的纠结和无耐。事情总是具有两面性，往好处看，这对我、对团队也未必是件坏事，没有经验过挫折和磨练，又怎能成佛呢？既然是组织需要或Boss的决定，那就多些理解和支持，支持和协助上级完成也是每个下属的职责；况且，某些变化至少对于一些同学也是件好事，他们有更多的机会和更大的平台去一展才华。<br />
<br />
大概人都是喜欢按习惯办事的缘故，每每有变化都觉的很痛苦。我觉的如何拥抱变化关键在于心态，我们需要理性看待变化，多往积极的方向思考，不仅更容易调整好心态，而且可以在变化中吸取经验和教训，鞭策我们成长。<br />
<br />
3）、提升项目管理能力<br />
虽然在项目管理知识上没有太多的时间和精力去系统的学习，但通过不断实践和总结，还是有了不少的积累和沉淀，对项目管理有了更多的理解和把握，对敏捷项目管理也有不同的认识，结合团队自身寻找适合我们的实践方式。在项目管理方面，还有很多需要去提升和学习，2011年希望安排更多的时间系统的学习项目管理知识及敏捷项目管理，并结合实际应用到工作中。<br />
<br />
4）、提升向上沟通力<br />
在拥抱变化的同时，同样需要理性的分析和积极的向上沟通。在过去，虽然会尽可能的去表达和反馈自己的想法和意见，但我重新审视下，总觉得表达还不够明确或不是那么的到位，或许在表达时还有更好的方式，至少还有提升的必要。向上沟通也是门学问，需要好好研究下。<br />
<br />
5)、提升团队建设和辅导能力<br />
相对来说，过去的一年所有的同学都会关注到，但领悟能力和基础较好的同学成长更快，基础稍弱的没有太大变化。显然，平常辅导工作没有做好或做到位，关注程度不够。越是基础差些的同学需要关注和帮助的点越多，需要帮助他们找到不足和问题所在，一起找改进办法，并给予必要的督促和检查，养成好的学习习惯，促进成长。2011年，这方面需要做的还有更多。<br />
<br />
<strong>2、谈谈2011年的期望</strong><br />
1）、团队<br />
解决目前团队新人多，有效资源少的问题；积极关注和帮助新人溶入团队，熟悉业务，以减少对项目开展的影响；<br />
抓好梯队建设，关注和辅导基础较差同学的，共同制定改进计划和Action，做好必要的监督和指导，促进成长；<br />
2）、能力<br />
系统学习项目管理和敏捷软件开发方面的知识，并应用到项目管理实践中；同时积极参与相关方面的分享和讨论。<br />
3）、影响<br />
推动兴趣小组活动的开展，借开发工具的发展和分享，建立团队在部门或技术部的影响；<br />
鼓励团队成员积极参与技术部的公共事务，提升影响力。<br />
<strong><br />
给力2010，加油2011!!!</strong><br />
<br />
 <img src ="http://www.blogjava.net/josson/aggbug/342882.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2011-02-02 21:46 <a href="http://www.blogjava.net/josson/archive/2011/02/02/342882.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈敏捷开发之稳定迭代周期的重要性</title><link>http://www.blogjava.net/josson/archive/2011/01/31/341341.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Mon, 31 Jan 2011 06:26:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2011/01/31/341341.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/341341.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2011/01/31/341341.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/341341.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/341341.html</trackback:ping><description><![CDATA[<span style="font-family: 微软雅黑;"><strong>1、什么是iteration和release？<br />
</strong>iteration和release是两个不同的概念，但在敏捷实践活动中，我们往往认识的比较模糊，一个Iteration就是一次release，其实不然。那么，具体有什么区别和联系呢？<br />
<strong>Iteration（迭代）</strong>：在固定的周期内，经过需求分析、设计、实现、测试等活动，完成计划的的业务需求，迭代结束提供一个可工作的产品。计划的业务需求，可能是一个完整的User Story，也可能是一个Story中的若干task。<br />
<strong>Release(发布)</strong>：经过一个或若干个iteration后，完成计划中的所有User Story，经过测试后才release，最终真正交付给客户使用。<br />
在我们的实践活动中，一个User Story所需的工作量超过我们的有效资源，无法安排在一个iteration内。我们就会想当然的会去延长迭代周期，增加有效资源以适应所需工作量。殊不知，这更象是形式上的迭代开发，无异于瀑布式项目开发过程。<br />
<br />
<strong>2、建立固定的迭代周期，保持稳定的开发节奏</strong><br />
Scurm方法也非常强调稳定的迭代节奏，一个稳定的迭代节奏就如同项目的的心跳。Simon Baker描述说："就像心脏有规律地跳动来保持身体运行，固定的迭代长度提供了一个恒量，有助于建立开发和交付的节奏。根据我的经验，节奏是帮助取得不变的步幅的重要因素"（2004）。对于敏捷开发的团队而言，稳定的迭代节奏可以让产品保持更稳定的交付。<br />
<br />
<strong>3、如何保持稳定的开发节奏？</strong><br />
当一个迭代期内可提供的有效资源无法实现一个User Story时，我们如何按排呢？ 在 <a href="../archive/2011/01/13/342927.html">谈迭代周期控制的困惑</a> 中已谈到，这里不在细述。<br />
<br />
<strong>4、如何选择适合自己团队的迭代周期？</strong><br />
一般需要考虑以下因素：<br />
1）、整个项目周期长度（完成计划的商业需求所需时间）<br />
较短的迭代周期将会有以下一些好处：更频繁的向客户展示/交付可用的软件；更频繁的度量开发进度；更频繁的取得反馈并改进；一般大的项目最好有多次(3次或以上)获取反馈、修正的机会，根据项目周期调整迭代周期长度。<br />
2）、不确定性的多少<br />
不确定性有多种形式，客户到底想要的是什么？小组的工作效率，时间？技术门槛等都不存在不确定性，不确定性越多，迭代就应该越短。<br />
3）、获得反馈的难易程度<br />
指小组获取反馈数量、频度和及时性，视所处的环境不同，选择合适的迭代长度；<br />
4）、优先级要以多久保持不变<br />
开发小组承诺在一次迭代中完成一组特定的功能，重要的是不要改变他们的目标方向，</span><span style="font-family: 微软雅黑;">优先级不会被改变的时间长度是选择迭代长度时需要考虑的因素。</span><br />
<span style="font-family: 微软雅黑;">
5）、迭代的系统开销<br />
每次迭代的成本（时间），如迭代中进行的完整回归测试。最佳迭代周期的目标之一就是减少或近似消除每次迭代的系统开销。如每次回归时间成本很高，那决定周期长度时更倾向于长一些。<br />
6）、团队成员的紧迫感<br />
Niels Malotaux指出："只要项目的结束日期还在遥远的将来，我们就不会感到任何压力，并从容不迫的工作。当结束日期逼近时，我们才会开始更努力的工作"。意思指项目开始大家比较放松，而越临近结束，工作越忙压力越大。因此，选择一个合适的迭代周期长度，让团队成员在整个迭代过程中感受到的压力更平均，不是给团队更多的压力，而是压力总量平均分布在迭代过程中。<br />
<br />
每个团队根据所在环境和条件确定一个合适的迭代长度，一般建议2~4周。在我们的实践中，以2周一次迭代的频率，保持相对稳定的开发和交付的节奏。<br />
<br />
<strong>5、参考资料:</strong><br />
《敏捷估计与规划》 Mike Cohn<br />
</span>
<img src ="http://www.blogjava.net/josson/aggbug/341341.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2011-01-31 14:26 <a href="http://www.blogjava.net/josson/archive/2011/01/31/341341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈自我管理</title><link>http://www.blogjava.net/josson/archive/2011/01/28/343721.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Fri, 28 Jan 2011 10:56:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2011/01/28/343721.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/343721.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2011/01/28/343721.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/343721.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/343721.html</trackback:ping><description><![CDATA[敏捷宣言中说到："最好的架构、需求和设计来自于自组织的团队"。在自组织团队中，我们每个人既是团队/项目的管理者，又是执行者，要取得优异的结果，必须加强自我管理。<br />
<br />
如何做好自我管理呢？<br />
<br />
<strong>1、平和的心态</strong>：我们会不断的遇到各类或好事或坏事、或成功或挫折，什么样的心态去对待决定了我们成长的方向及高度，"态度决定一切"。<br />
<strong>2、目标感</strong>：大到个人职业规划，小到每件事的期望，对于目标(期望)的制定和管理，都需要我们认真的去对待；<br />
<strong>3、执行力</strong>：目标是方向，不能执行就不会有结果，好的执行力是优秀个人或团队的必要条件。<br />
<strong>4、时间管理</strong>：工作需要区分轻重缓急，不能对事情没有计划和按排，对事需要分析重要性和紧急程度，分别对待；<br />
<strong>5、学习能力</strong>："学历代表过去，能力代表现在，学习能力代表将来。"，一个人的学习能力决定他将来的成绩；<br />
<br />
任何人都不希望自己被人管着，但要想不被人管只有一种办法：时时严格要求自己，主动、出色的完成每项工作，努力学习，与团队共成长。<br />
<img src="file:///C:/DOCUME%7E1/JIANFA%7E1.JIN/LOCALS%7E1/Temp/moz-screenshot.png" alt="" /><img src="file:///C:/DOCUME%7E1/JIANFA%7E1.JIN/LOCALS%7E1/Temp/moz-screenshot-1.png" alt="" /><img src="file:///C:/DOCUME%7E1/JIANFA%7E1.JIN/LOCALS%7E1/Temp/moz-screenshot-2.png" alt="" /><img src="file:///C:/DOCUME%7E1/JIANFA%7E1.JIN/LOCALS%7E1/Temp/moz-screenshot-3.png" alt="" /><img src="file:///C:/DOCUME%7E1/JIANFA%7E1.JIN/LOCALS%7E1/Temp/moz-screenshot-4.png" alt="" />
<img src ="http://www.blogjava.net/josson/aggbug/343721.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2011-01-28 18:56 <a href="http://www.blogjava.net/josson/archive/2011/01/28/343721.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈迭代周期控制的困惑</title><link>http://www.blogjava.net/josson/archive/2011/01/13/342927.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Thu, 13 Jan 2011 07:31:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2011/01/13/342927.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/342927.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2011/01/13/342927.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/342927.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/342927.html</trackback:ping><description><![CDATA[昨日PM小组例会，谈到了需求评估工作量远大于有效资源情况下，如何保证迭代周期稳定的问题。讨论的内容，对于PM如何控制、保持迭代周期稳定有较大的参考价值。<br />
<br />
<table border="0" cellpadding="0" cellspacing="0" width="267">
    <tbody>
        <tr style="height: 17.25pt;" height="23">
            <td class="xl66" style="height: 17.25pt; width: 36pt;" width="48" height="23">　</td>
            <td class="xl67" style="width: 78pt;" width="104">有效资源</td>
            <td class="xl67" style="width: 86pt;" width="115">评估工作量</td>
        </tr>
        <tr style="height: 13.5pt;" height="18">
            <td class="xl65" style="height: 13.5pt;" height="18">1</td>
            <td class="xl65">多</td>
            <td class="xl65">少</td>
        </tr>
        <tr style="height: 13.5pt;" height="18">
            <td class="xl65" style="height: 13.5pt;" height="18">2</td>
            <td class="xl65">少</td>
            <td class="xl65">多</td>
        </tr>
        <tr style="height: 13.5pt;" height="18">
            <td class="xl65" style="height: 13.5pt;" height="18">3</td>
            <td class="xl65">相同</td>
            <td class="xl65">相同</td>
        </tr>
    </tbody>
</table>
注：<br />
有效资源：指迭代周期内，开发团队所能提供的有效工作日，单位人/天。<br />
评估工作量：指迭代周期内，产品经理提供需要实现的业务需求所评估的工作量之和。<br />
<br />
上表描述以固定周期为两周的迭代中，可能会出现的有效资源和评估工作量对比情况。其中，1、3两种情况因为评估工作量小于或等同能提供的有效资源，所以不会影响迭代周期。重点需讨论的是有效资源小于评估工作量时，如何保持固定周期？<br />
<br />
例举：一迭代周期，能提供有效资源20人/天，需求评估工作量30人/天。<br />
1、功能较独立，需求不能拆分发布；<br />
安排一个release，两个iterative。这种情况需要在迭代2中附加一些技术改造或低优先级的小需求、bugfix，release日期相对会慢几天。<br />
<br />
2、一个迭代中包括多个产品的需求(需要各位产品经理协商，决定需求优先级)；<br />
a)、以保证质量为重：<br />
忽略商业优先级，先处理一个迭代中就能全部完成的需求。<br />
<br />
b)、保证价值<br />
分两个迭代完成，一次release。<br />
<br />
通常情况下，我们尽力保证迭代周期的稳定，但也允许例外，如：商业需求，产品上确定了发布时间点，或者节假期间团队请假比较多，一个迭代所能提供的有效资源相对比较少的情况。<br />
<br />
保持迭代周期稳定，其核心是：<strong>固定Timebox和可提供的资源，让产品经理来决定需求的优先级，每迭代只接纳(开发/QA资源)可承受的需求。</strong><br />
<img src ="http://www.blogjava.net/josson/aggbug/342927.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2011-01-13 15:31 <a href="http://www.blogjava.net/josson/archive/2011/01/13/342927.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>敏捷项目管理序</title><link>http://www.blogjava.net/josson/archive/2010/12/16/340902.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Thu, 16 Dec 2010 07:57:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2010/12/16/340902.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/340902.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2010/12/16/340902.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/340902.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/340902.html</trackback:ping><description><![CDATA[对于互联网行业来说，快速推出产品占领市场、快速检验产品的价值和方向性、快速调整及优化是极期重要的。因此，采用小步快跑、持续迭代的敏捷实践一种不错的项目管理方法。我们团队在敏捷项目管理方面持续开展了二年多时间，在scrum、xp等敏捷最佳实践的基础上，结合团队自身的基础和条件，不断的偿试和优化，总结和积累了一些经验。目前，这些敏捷项目管理实践在项目组开展情况良好，得到了大多数团队成员的认同，特别是业务方、QA等合作方的认可。<br />
<br />
<img src="http://www.blogjava.net/images/blogjava_net/josson/agile_flow.png" alt="" border="0" /><br />
上图描述了一个基本项目迭代流程，其中涉及三个角色，其职责同等于Scrum中的Product Owner、Scrum Master、Scrum Team。迭代流程中分别包含了以下敏捷实践：<br />
1）、迭代计划会议，按商业优先级筛选需求列表，确定本项目需求范围；<br />
2）、确认本次迭代需求、资源、时间的具体情况；<br />
3）、简单设计，对关键技术点进行必要的设计；<br />
4）、晨会；<br />
5）、结对编程；<br />
6）、持续集成；<br />
7）、showcase；<br />
8）、项目总结会；<br />
9）、新迭代的开始... ...<br />
<br />
以上具体实践活动内容及组织形式，后续将逐一介绍，敬请关注。<br />
<img src ="http://www.blogjava.net/josson/aggbug/340902.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2010-12-16 15:57 <a href="http://www.blogjava.net/josson/archive/2010/12/16/340902.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java序列化算法原理</title><link>http://www.blogjava.net/josson/archive/2010/12/16/332685.html</link><dc:creator>josson</dc:creator><author>josson</author><pubDate>Thu, 16 Dec 2010 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/josson/archive/2010/12/16/332685.html</guid><wfw:comment>http://www.blogjava.net/josson/comments/332685.html</wfw:comment><comments>http://www.blogjava.net/josson/archive/2010/12/16/332685.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/josson/comments/commentRss/332685.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/josson/services/trackbacks/332685.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><strong>1、什么是java序列化</strong><br />
</p>
<p class="MsoNormal"><span lang="EN-US">Java</span>
<span style="font-family: SimSun;">序列化</span>
<span lang="EN-US">API</span>
<span style="font-family: SimSun;">提供一种处理对象序列化的标准机制。</span><u><span style="font-family: SimSun;">序列化</span><span style="font-family: SimSun;">（</span><span lang="EN-US">Serialization</span></u><span style="font-family: SimSun;"><u>）</u>是指将java对象用一连串字节描述的一个过程；反序列化</span>（<span class="SpellE"><span lang="EN-US">deserialization</span>）</span><span style="font-family: SimSun;">是一种将这一串字节构建成一个对象的过程。</span></p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal"><strong><span style="font-family: SimSun;">2、序列化的作用（必要性）</span></strong></p>
<p class="MsoNormal"><span lang="EN-US">Java</span><span style="font-family: SimSun;">中，一切都是对象，在分布式环境中经常需要将</span>对象<span style="font-family: SimSun;">从这一端网络或设备传递到另一端。</span><span lang="EN-US">Java</span>
<span style="font-family: SimSun;">序列化机制就是一种解决</span><span style="font-family: SimSun;">在网络两端传输数据的问题而产生的协议。</span><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span class="Apple-style-span" style="color: rgb(68, 68, 68); font-family: Verdana,sans-serif; font-size: 14px; line-height: 26px;">下图表示客户端/服务器之间通信，一个对象是从客户端传送到服务器通过序列化的视图。</span></span></p>
<p class="MsoNormal"><span style="font-family: SimSun;"><img src="http://www.blogjava.net/images/blogjava_net/josson/jtip050709-fig1.gif" alt="" border="0" width="605" height="270" /></span></p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal"><strong><span style="font-family: SimSun;">3、如何序列化一个对象</span>
</strong>
</p>
<p class="MsoNormal"><span style="font-family: SimSun;">为序列化一个对象，你需确保对象类实现</span><span class="SpellE"><span lang="EN-US">Serializable</span></span><span style="font-family: SimSun;">接口。</span><span class="SpellE"><span lang="EN-US">Serializable</span></span><span style="font-family: SimSun;">接口没有方法，只要实现了序列化接口，</span><span lang="EN-US">Class</span>
<span style="font-family: SimSun;">就能被序列化机制处理。</span></p>
<p class="MsoNormal"><span style="font-family: SimSun;">示例代码，需序列化的java对象:<br />
</span>
</p>
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 128, 128);">1</span>&nbsp;<span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);">&nbsp;java.io.Serializable;<br />
</span><span style="color: rgb(0, 128, 128);">2</span>&nbsp;<span style="color: rgb(0, 0, 0);"><br />
</span><span style="color: rgb(0, 128, 128);">3</span>&nbsp;<span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;TestClassSerial&nbsp;</span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);">&nbsp;Serializable&nbsp;&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">4</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);">&nbsp;version&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">;<br />
</span><span style="color: rgb(0, 128, 128);">5</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);">&nbsp;count&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;&nbsp;&nbsp;<br />
</span><span style="color: rgb(0, 128, 128);">6</span>&nbsp;<span style="color: rgb(0, 0, 0);">}<br />
</span></div>
<br />
示例代码，<span style="font-family: SimSun;">把</span>TestClassSerial对照象<span style="font-family: SimSun;">输出成</span>
<span lang="EN-US">Byte</span>
<span style="font-family: SimSun;">流，</span><span style="font-family: SimSun;">存储到</span>
<span class="SpellE"><span lang="EN-US">temp.out</span>
</span>
<span style="font-family: SimSun;">文件里：</span>
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 128, 128);">&nbsp;1</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;main(String&nbsp;args[])&nbsp;</span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);">&nbsp;IOException&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;2</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileOutputStream&nbsp;fos&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;3</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectOutputStream&nbsp;oos&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;4</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;5</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fos&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;FileOutputStream(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">c:/temp.out</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;6</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oos&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;ObjectOutputStream(fos);<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;7</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TestClassSerial&nbsp;tcs&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;TestClassSerial();<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;8</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oos.writeObject(tcs);<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;9</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oos.flush();<br />
</span><span style="color: rgb(0, 128, 128);">10</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0, 128, 128);">11</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">12</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(oos&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">13</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oos.close();<br />
</span><span style="color: rgb(0, 128, 128);">14</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0, 128, 128);">15</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(fos&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">16</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fos.close();<br />
</span><span style="color: rgb(0, 128, 128);">17</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0, 128, 128);">18</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0, 128, 128);">19</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
示例代码，<span style="font-family: SimSun;">从持久的文件中读取</span>
<span lang="EN-US">Bytes</span>
<span style="font-family: SimSun;">重建对象</span><span class="SpellE">：</span>
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 128, 128);">&nbsp;1</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">&nbsp;main1(String&nbsp;args[])&nbsp;</span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);">&nbsp;IOException&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;2</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileInputStream&nbsp;fis&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;&nbsp;<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;3</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectInputStream&nbsp;oin&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;4</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;5</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fis&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;FileInputStream(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">c:/temp.out</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;6</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oin&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);">&nbsp;ObjectInputStream(fis);<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;7</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TestClassSerial&nbsp;tcs&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;(TestClassSerial)&nbsp;oin.readObject();<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;8</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">version=</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">tcs.version);<br />
</span><span style="color: rgb(0, 128, 128);">&nbsp;9</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0, 128, 128);">10</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);">&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">11</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(fis&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">12</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fis.close();<br />
</span><span style="color: rgb(0, 128, 128);">13</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0, 128, 128);">14</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(oin&nbsp;</span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)&nbsp;{<br />
</span><span style="color: rgb(0, 128, 128);">15</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oin.close();<br />
</span><span style="color: rgb(0, 128, 128);">16</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0, 128, 128);">17</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: rgb(0, 128, 128);">18</span>&nbsp;<span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<span style="font-family: SimSun;"><span>
<p class="MsoNormal">执行结果为：<span lang="EN-US">100.</span></p>
<p class="MsoNormal"><br />
</p>
<p class="MsoNormal"><strong><span style="font-family: SimSun;">4、对象的序列化格式</span></strong></p>
</span></span>
<p class="MsoNormal"><span style="font-family: SimSun;">TestClassSerial对象序列化输出的</span>
<span class="SpellE"><span lang="EN-US">temp.out</span>
</span>
<span style="font-family: SimSun;">文件，以</span>
<span lang="EN-US">16</span>
<span style="font-family: SimSun;">进制方式显示，内容如下：</span></p>
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 0, 0);">AC&nbsp;ED&nbsp;</span><span style="color: rgb(0, 0, 0);">00</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">05</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">73</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">72</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">00</span><span style="color: rgb(0, 0, 0);">&nbsp;0A&nbsp;</span><span style="color: rgb(0, 0, 0);">53</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">65</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">72</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">69</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">61</span><span style="color: rgb(0, 0, 0);">&nbsp;6C&nbsp;</span><span style="color: rgb(0, 0, 0);">54</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">65</span><span style="color: rgb(0, 0, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">73</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">74</span><span style="color: rgb(0, 0, 0);">&nbsp;A0&nbsp;0C&nbsp;</span><span style="color: rgb(0, 0, 0);">34</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">00</span><span style="color: rgb(0, 0, 0);">&nbsp;FE&nbsp;B1&nbsp;DD&nbsp;F9&nbsp;</span><span style="color: rgb(0, 0, 0);">02</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">00</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">02</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">42</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">00</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">05</span><span style="color: rgb(0, 0, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">63</span><span style="color: rgb(0, 0, 0);">&nbsp;6F&nbsp;</span><span style="color: rgb(0, 0, 0);">75</span><span style="color: rgb(0, 0, 0);">&nbsp;6E&nbsp;</span><span style="color: rgb(0, 0, 0);">74</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">42</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">00</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">07</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">76</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">65</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">72</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">73</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">69</span><span style="color: rgb(0, 0, 0);">&nbsp;6F&nbsp;6E&nbsp;</span><span style="color: rgb(0, 0, 0);">78</span><span style="color: rgb(0, 0, 0);"><br />
</span><span style="color: rgb(0, 0, 0);">70</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">00</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">64</span></div>
<p class="MsoNormal"><span style="font-family: SimSun;"><span>
<p class="MsoNormal"><span style="font-family: SimSun;"><span>这些二进制字节就是用来描述序列化以后的</span></span><span class="SpellE"><span lang="EN-US">TestClassSerial</span></span><span style="font-family: SimSun;">对象的，我们注意到</span>
<span class="SpellE"><span lang="EN-US">TestSerial</span>
</span>
<span style="font-family: SimSun;">类中只有两个域：</span></p>
</span>
</span>
</p>
<div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; width: 98%;"><span style="color: rgb(0, 128, 128);">1</span>&nbsp;<span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);">&nbsp;version&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">100</span><span style="color: rgb(0, 0, 0);">;<br />
</span><span style="color: rgb(0, 128, 128);">2</span>&nbsp;<span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">byte</span><span style="color: rgb(0, 0, 0);">&nbsp;count&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;</span></div>
<p class="MsoNormal">
</p>
<p class="MsoNormal"><span style="font-family: SimSun;">都是</span>
<span lang="EN-US">byte</span>
<span style="font-family: SimSun;">型，理论上存储这两个域只需要</span>
<span lang="EN-US">2</span>
<span style="font-family: SimSun;">个</span>
<span lang="EN-US">byte</span>
<span style="font-family: SimSun;">，但是实际上</span>
<span class="SpellE"><span lang="EN-US">temp.out</span>
</span>
<span style="font-family: SimSun;">占据空间为</span>
<span lang="EN-US">51bytes</span>
<span style="font-family: SimSun;">，也就是说除了数据以外，还包括了对序列化对象的其他描述。</span></p>
<p class="MsoNormal"><span style="font-family: SimSun;"><br />
</span></p>
<p class="MsoNormal"><strong><span lang="EN-US">5、Java</span>
</strong>
<strong><span style="font-family: SimSun;">的序列化算法</span>
</strong>
</p>
<p class="MsoNormal"><span style="font-family: SimSun;">序列化算法一般会按步骤做如下事情：</span>
</p>
<p class="MsoNormal"><span style="font-family: Wingdings;"><span>1、</span></span><span style="font-family: Wingdings;">将对象实例相关的类的元数据输出；<br />
<span>2、</span></span><span style="font-family: Wingdings;">递归地输出类的超类元数据描述直到不再有超类；<br />
<span>3、</span></span><span style="font-family: Wingdings;">类元数据完了以后，开始从最顶层的超<span class="GramE">类开始</span>输出对象实例的实际数据值；<br />
<span>4、</span></span><span style="font-family: SimSun;">从上至下递归输出实例的数据；</span></p>
<p class="MsoNormal"><span style="font-family: SimSun;"><br />
</span></p>
<p class="MsoNormal"><span style="font-family: SimSun;">更多序例化事例及二进制字节含义参考文档：http://my.oschina.net/god/blog/1291</span></p>
<p class="MsoNormal">
</p>
<span style="font-family: SimSun;"><span>
<p class="MsoNormal">
</p>
</span></span>
<p class="MsoNormal"> </p>
<img src ="http://www.blogjava.net/josson/aggbug/332685.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/josson/" target="_blank">josson</a> 2010-12-16 14:52 <a href="http://www.blogjava.net/josson/archive/2010/12/16/332685.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>