﻿<?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-Binge's Blog-文章分类-Java综合技术</title><link>http://www.blogjava.net/batistuta/category/17811.html</link><description>网络文摘集（Java篇）</description><language>zh-cn</language><lastBuildDate>Thu, 01 Mar 2007 18:27:15 GMT</lastBuildDate><pubDate>Thu, 01 Mar 2007 18:27:15 GMT</pubDate><ttl>60</ttl><item><title>通过 IDE 使用 Subversion</title><link>http://www.blogjava.net/batistuta/articles/84333.html</link><dc:creator>batistuta</dc:creator><author>batistuta</author><pubDate>Wed, 29 Nov 2006 05:36:00 GMT</pubDate><guid>http://www.blogjava.net/batistuta/articles/84333.html</guid><wfw:comment>http://www.blogjava.net/batistuta/comments/84333.html</wfw:comment><comments>http://www.blogjava.net/batistuta/articles/84333.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/batistuta/comments/commentRss/84333.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/batistuta/services/trackbacks/84333.html</trackback:ping><description><![CDATA[
		<p>您可通过命令行使用 Subversion，但若将其与您的 IDE 集成更为便捷。IntelliJ IDEA 5.0 及后续版本均包含对 Subversion 的内置支持。NetBeans 还不支持 Subversion，但相关工作已经在开展，未来版本中将提供支持。对于 Eclipse，您需要安装 Subclipse 插件。本文使用 Eclipse 作为 IDE。</p>
		<p>Subclipse 的安装与其他 Eclipse 插件类似：</p>
		<ol>
				<li>在 Eclipse 中，选择 <b>Help Software Updates | Find and Install...</b>。<br /><br /></li>
				<li>在向导的第一个面板中，单击 <b>Search for new features to install</b> 单选按钮，并单击 <b>Next</b>。<br /><br /></li>
				<li>在向导的第二个面板中，单击 <b>New Remote Site</b>。输入 <code>Subclipse</code> 作为名称，输入 <code>http://subclipse.tigris.org/update_1.0.x</code> 作为 URL。然后单击 <b>Finish</b>。 <br /><br />这将启动另外一个小的向导。下一个对话框应为您提供一个可安装的特性 —— Subclipse。选中它并单击 <b>Next</b>。<br /><br /></li>
				<li>接受许可协议，完成安装。<br /><br /></li>
		</ol>
		<p>程序包目前未经过数字签名，但只要您是按照第三步的 URL 下载的，就是安全的。</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N100E8">
																				<b>Subversion 快捷方式</b>
																		</a>
																		<br />
																		<p>如果您目前常常使用 Subversion，您可能希望将其添加到 Eclipse 的 New、Open Perspective 和 Show View 菜单中。为此，选择 <b>Window/Customize Perspective...</b> 并在 Shortcut 分类列表中选中 <b>SVN</b>。这将使您可在目前可看到 CVS 的所有菜单中访问 Subversion。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>安装程序包后，您必须重新启动 Eclipse，随后才能使用 Subversion。完成之后，您就可以与如今使用 CVS 大体相同的方式使用 Subversion 了，只有为数不多的区别。</p>
		<p>
				<a name="N100FA">
						<span class="atitle">
								<font face="Arial" size="4">检出项目</font>
						</span>
				</a>
		</p>
		<p>设置一个新的 Subversion 存储库，特别是网络存储库相对来说较为复杂。但若您正在连接一个现有项目，第一次检出文件就相当轻松。在 <b>File</b> 菜单中选择 <b>New/Other...</b>。这些步骤将为您打开如 图 1 所示的对话框：</p>
		<br />
		<a name="figure1">
				<b>图 1. 通过 Subversion 启动一个新项目</b>
		</a>
		<br />
		<img height="445" alt="通过 SVN 检出项目" hspace="5" src="http://www-128.ibm.com/developerworks/cn/java/j-subversion/selectwizard.jpg" width="525" vspace="5" border="0" />
		<br />
		<p>接下来，打开 SVN 文件夹，选择 <b>Select Checkout Projects from SVN</b>，并单击 <b>Next</b> 以显示如图 2 所示的对话框：</p>
		<br />
		<a name="figure2">
				<b>图 2. Select/Create Location</b>
		</a>
		<br />
		<img height="368" alt="Select/Create Location" hspace="5" src="http://www-128.ibm.com/developerworks/cn/java/j-subversion/selectlocation.jpg" width="418" vspace="5" border="0" />
		<br />
		<p>第一次从存储库检出时，您需要选择 <b>Create a new repository location</b> 并单击 <b>Next</b>。这将为您打开如图 3 所示的对话框：</p>
		<br />
		<a name="figure3">
				<b>图 3. 为存储库键入 URL</b>
		</a>
		<br />
		<img height="368" alt="为存储库键入 URL" hspace="5" src="http://www-128.ibm.com/developerworks/cn/java/j-subversion/locationurl.jpg" width="418" vspace="5" border="0" />
		<br />
		<p>您在这里提供存储库的 URL。这只是一个普通的 http URL，如 http://svn.apache.org/repos/asf/xerces/java/。这一次单击 <b>Next</b> 时，Eclipse 连接到存储库，并查找可检出的文件夹。通常有三个文件夹：branches、tags 和 trunk，如图 4 所示。Branches 文件夹用于试验。Tags 通常标识较老的、已发布的软件版本。而大多数时候，您都希望在主分支上工作（CVS 称之为 HEAD），因此选择 <b>trunk</b> 并单击 <b>Next</b>。</p>
		<br />
		<a name="figure4">
				<b>图 4. 选择要检出的修订版</b>
		</a>
		<br />
		<img height="334" alt="选择文件夹" hspace="5" src="http://www-128.ibm.com/developerworks/cn/java/j-subversion/selectfolder.jpg" width="417" vspace="5" border="0" />
		<br />
		<p>您现在有两个选择：<b>Check out as a Project configured using the New Project Wizard</b> 或 <b>Check out as a project in the workspace</b>，如图 5 所示。您可按自己的需要任意选择，您可能希望为项目命名，因为默认名称为 “trunk”。最后，单击 <b>Finish</b>。</p>
		<br />
		<a name="figure5">
				<b>图 5. 检出项目的两种方法</b>
		</a>
		<br />
		<img height="334" alt="检出项目的两种方法" hspace="5" src="http://www-128.ibm.com/developerworks/cn/java/j-subversion/checkoutas.jpg" width="417" vspace="5" border="0" />
		<br />
		<p>Eclipse 现在从您选择的分支、主干或标记中下载所有源文件。如果您选择的是 <b>Check out as a project in the workspace</b>，则必须完成 Eclipse 的 New Project 向导，以设置编译器级别、项目布局和其他选项。如果您未使用 New Project 向导，则需要手动设置构建路径和其他选项，就像您在自己的文件系统的一个目录中创建了一个项目那样。确实，您所做的与那极为相似。所有文件都是本地存储的。对于构建、运行和调试这样的普通操作，Eclipse 不关心文件是否已为版本控制检出。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-subversion/index.html#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10190">
						<span class="atitle">
								<font face="Arial" size="4">验证设置</font>
						</span>
				</a>
		</p>
		<p>此时，最好进行一次快速、明智的检查，确保您已正确地设置了构建路径。如果没有明显的问题，并且能够运行单元测试，那么即可放心地继续下去了。</p>
		<p>如果存在问题，检查项目属性，以确保正确地设置了源路径和类路径。使之差一非常常见，无论是多一还是少一。因此，最终 Eclipse 会认为您的类的名称类似于 <code>src.org.apache.xerces.parsers.SAXParser</code> 或 <code>apache.xerces.parsers.SAXParser</code>，而不是 <code>org.apache.xerces.parsers.SAXParser</code>。在多文件夹项目中，Eclilpse 也常常会错误地将一个数据文件夹标记为源文件夹或遗漏了一个源文件夹。如果发生了以上任何一种小故障，您都必须修复错误，然后才能基础。</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N101AB">
																				<b>多文件提交</b>
																		</a>
																		<br />
																		<p>Subversion 可在一个原子操作中提交数个文件（与之形成对比，CVS 将每一个分开的文件视为一次独立提交）。为此，只需在 Package Explorer 中选择您想提交的所有文件（按住 ctrl 键或 Command 键，然后依次单击所需文件），然后在上下文菜单中选择 <b>Team/Commit...</b> 即可。如果您随后需要取消更改或将存储库回复到特定更改之前的状态，这种方法非常有用。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>要检查错误，选择 <b>Project | Properties</b>，然后找到 <b>Java Build Path</b>。您可在 <b>source</b> 选项卡中修订任何向导做错的地方。您可能还要添加另外一个项目需要的 JAR 归档，Eclpse 在检出时不会注意到此归档。您还可在 <b>library</b> 选项卡的 <b>Java Build Path</b> 中添加此归档。</p>
		<p>请做好心理准备，您可能要在这里花上一点时间。Eclipse 很少会在第一次就让一切正确无误，每个项目组织其文件和库的方式又总会有所不同。</p>
		<p>
				<a name="N101CC">
						<span class="atitle">
								<font face="Arial" size="4">与存储库同步</font>
						</span>
				</a>
		</p>
		<p>接下来您就可以照常编辑文件了。作出您希望的任何更改。运行单元测试。优化代码。更正注释中的拼写错误。完成部分工作后，使用上下文菜单并选择 <b>Team/Commit...</b>。您将看到图 6 所示的对话框，要求您输入提交注释：</p>
		<br />
		<a name="figure6">
				<b>图 6. Subclipse 的提交对话框</b>
		</a>
		<br />
		<img height="456" alt="提交" hspace="5" src="http://www-128.ibm.com/developerworks/cn/java/j-subversion/commitdialog.jpg" width="555" vspace="5" border="0" />
		<br />
		<p>同样，若其他人更改了您希望应用于您的副本的存储库，只要在 Package Explorer 中选中文件，并从上下文菜单中选择 <b>Team/Update</b> 即可。这会以主副本替换您的副本。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-subversion/index.html#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N101F0">
						<span class="atitle">
								<font face="Arial" size="4">合并</font>
						</span>
				</a>
		</p>
		<p>如果您已进行了更改，其他开发人员也进行了更改，那么您就必须手动合并文件。对于绝大多数简单更改，Subversion 可推断出需要进行怎样的处理，无需人工干预。但对于较大、较为复杂、存在冲突的更改，您可能需要参与进来，手动合并更改。</p>
		<p>Subclipse 在这里可提供一些帮助，但实际上我发现，在一个独立的窗口或选项卡中直接实现一个临时文件副本，通过存储库更新本地副本以覆盖我的更改，然后通过临时副本重新输入更改，这样做往往更容易。若存储库中的更改与我做出的更改相比较少，我就会从存储库实现临时副本，并通过它进行提交，而不是更新。随后我会重新应用那些更改。这听上去非常复杂，但事实通常并非如此，它的发生几率几乎与您希望的一样低。即便是您出了错，忘记重新应用更改或是错误地应用了更改，总是可以找到所有更改的完整历史（包括您覆盖的那些更改）供您参考。实际上您从未彻底丢失任何东西。</p>
		<p>如果您不确定已更改了哪些文件，同步视图可以为您显示这些文件。您还可打开标签修饰（label decoration）来查看上次提交/更新后哪些文件发生过更改。选择 <b>Help | Preferences</b>，然后再选择 <b>General/Appearance/Label Decorations</b>。然后选中 <b>SVN 复选框</b>。（实际上该复选框在默认情况下就是选中的。）</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-subversion/index.html#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10208">
						<span class="atitle">
								<font face="Arial" size="4">修补</font>
						</span>
				</a>
		</p>
		<p>如果您不具备正在使用的存储库的提交权限，就需要制作一个修补程序，然后将其发送给维护人员。只要选中您希望比较的文件，然后从上下文菜单中选择 <b>Team/Create Patch...</b> 即可。您可以随自己的方便将修补程序保存到文件或剪贴板中。随后可通过电子邮件将其发送给维护人员，或者在 bug 报告中附上该修补程序。修补程序本身采用的格式与 CVS 所使用的 diff 格式相同。</p>
		<p>应用他人发送给您的修补程序就没那么复杂了，只要选中您想修补的文件或项目。从上下文菜单中选择 <b>Team/Apply Patch...</b> ，然后平台上惯用的 open file 对话框选择修补程序文件即可。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-subversion/index.html#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N1021A">
						<span class="atitle">
								<font face="Arial" size="4">比较</font>
						</span>
				</a>
		</p>
		<p>如果您已作出了一些更改，并且希望看看您的副本与存储库中的版本有怎样的差别，只需在上下文菜单中选择 <b>Compare/Latest From Repository</b> 即可。这实际上与 CVS 中比较功能的工作方式完全相同。图 7 显示了比较功能的工作情况：</p>
		<br />
		<a name="figure7">
				<b>图 7. 在 Subclipse 中比较两个文件</b>
		</a>
		<br />
		<img height="288" alt="" hspace="5" src="http://www-128.ibm.com/developerworks/cn/java/j-subversion/smalldiff.jpg" width="558" vspace="5" border="0" />
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-subversion/index.html#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10237">
						<span class="atitle">
								<font face="Arial" size="4">删除</font>
						</span>
				</a>
		</p>
		<p>删除文件也很轻松。只要在 Eclipse 的程序包管理器中删除文件，然后提交父文件夹即可。删除目录要略微复杂一点。您可以选择一个目录并删除它。目录中的所有文件将会立即被删除。但在您删除后，目录本身及其所有子目录又会立即出现在原来的位置。要真正地删除一个文件夹，您需要选中 “已删除” 的文件夹并提交它。同一规则也适用于将一个文件从一个位置移动到另外一个位置的情况。</p>
		<table cellspacing="0" cellpadding="0" width="40%" align="right" border="0">
				<tbody>
						<tr>
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td>
										<table cellspacing="0" cellpadding="5" width="100%" border="1">
												<tbody>
														<tr>
																<td bgcolor="#eeeeee">
																		<a name="N10243">
																				<b>小心！</b>
																		</a>
																		<br />
																		<p>Apache 项目将源代码提交到了不属于自己、现在也无法删除的 Subversion 存储库中，使自己陷入麻烦。Apache 可以隐藏代码，但如果您知道到哪儿去看，您会发现这些代码就在那儿。拥有源代码的人可能是恶意的，也有可能向 Apache 的 ISP 发送一条 DMCA 下线通知，从而使 Apache 脱离 Internet。Apache 惟一的防御措施就是彻底删除其存储库。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<p>在您删除了一个文件或一个文件夹之后，依然可以通过存储库使其还原，即便是已经提交了删除。一旦您将任何内容放进存储库，那么就永远不会真正、永久地失去它，这有时候会产生问题。例如，假设您发现有人意外的检入了其整个主目录，包括其 Quicken 数据文件和所有来自其爱人的情书归档。您很希望能够<i>彻底消除</i> 这些被误提交的文件，这样就不会有其他人得到这些文件。尽管这是一个非同寻常的操作（无论如何，版本控制系统的目的就在于永远地保留每一个文件的每个修订版），但有时也是必要的。令人沮丧的是，Subversion 漏掉了这个重要的特性。</p>
		<p>由于没有彻底消除的命令，所以我在为外部可见的存储库使用 Subversion 时非常不安。CVS 也没有这样的命令，但在 CVS 中，您完全有可能在不毁掉存储库的情况下手动删除错误提交的文件。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-subversion/index.html#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10256">
						<span class="atitle">
								<font face="Arial" size="4">结束语</font>
						</span>
				</a>
		</p>
		<p>对于内部存储库，Subversion 提供了远超过 CVS 的改进。如果添加了某种类型的彻底消除功能，它也应同样适于外部存储库。尽管像 Eclipse 这样的工具对 Subversion 的第三方支持还不像 CVS 支持那样普遍，但形势正在迅速地发生变化。Subversion 会成为新项目的默认源代码存储库。尚无源代码控制的现有项目应尽快检入 Subversion。而已有 CVS 存储库的现有项目可能仍在观望，希望等到他们所依赖的全部工具均全面支持 Subversion 后再进行切换。但这些项目最终也会移植到 Subversion。Subversion 中的改进如此显著，令人难以忽略。未来必将属于 Subversion。</p>
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																		<br />
																</td>
																<td valign="top" align="right">
																		<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/j-subversion/index.html#main">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="resources">
						<span class="atitle">
								<font face="Arial" size="4">参考资料 </font>
						</span>
				</a>
		</p>
		<b>学习</b>
		<br />
		<ul>
				<li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/java/library/j-subversion/?S_TACT=105AGX52&amp;S_CMP=cn-a-j" target="_blank">英文原文</a> 。<br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/opensource/library/os-ecshare/?S_TACT=105AGX52&amp;S_CMP=cn-a-j">Sharing code with the Eclipse Platform</a>”（Pawel Leszek，developerWorks，2003 年 3 月）：简要介绍了 Eclipse 平台处理源代码版本控制的方式。<br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/cn/views/opensource/tutorials.jsp?cv_doc_id=108167">利用 PHP 和 Subversion 从零开始创建一个 blog</a>”（Tyler Anderson，developerWork，2006 年 2 月）：一份介绍使用 PHP 和 Subversion 进行 Web 开发的教程。<br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/cn/java/j-cc/index.html">自动进行团队构建和单元测试过程</a>”（Mark Wilkinson，developerWorks，2005 年 10 月）：创建一个自动化系统，以使用 CVS 和 Subversion（及其他工具）构建并测试您的源代码。<br /><br /></li>
				<li>“<a href="http://www.pragmaticprogrammer.com/titles/svn2/">Pragmatic Version Control using Subversion, 2nd Edition</a>”（Mike Mason，Pragmatic Programmers，2006 年 5 月）：全面的 Subversion 用法介绍。<br /><br /></li>
				<li>
						<i>
								<a href="http://svnbook.red-bean.com/">Version Control with Subversion</a>
						</i>（Ben Collins-Sussman，Brian W. Fitzpatrick，C. Michael Pilato；O'Reilly Media）关于 Subversion 的免费在线图书。<br /><br /></li>
				<li>
						<a href="https://sourceforge.net/">Sourceforge</a>：为开放源码项目提供免费的 Subversion 宿主。<br /><br /></li>
				<li>
						<a href="http://www.ibm.com/developerworks/cn/java/">Java 技术专区</a>：数百篇关于 Java 编程各个方面的文章。</li>
		</ul>
		<br />
		<b>获得产品和技术</b>
		<br />
		<ul>
				<li>
						<a href="http://subversion.tigris.org/">Subversion</a>：针对不同平台的开放源码及二进制版本。<br /><br /></li>
				<li>
						<a href="http://subclipse.tigris.org/">Subclipse</a>：Eclipse Subversion 插件。<br /><br /></li>
				<li>
						<a href="http://subversion.netbeans.org/teepee/index.html">Teepee</a>：NetBeans Subversion 项目。<br /><br /></li>
				<li>
						<a href="http://companions.jetbrains.com/tmate/">TMate</a>：IntelliJ IDEA Subversion 插件。<br /><br /></li>
		</ul>
		<br />
		<b>讨论</b>
		<br />
		<ul>
				<li>
						<a href="http://www.ibm.com/developerworks/blogs/?S_TACT=105AGX52&amp;S_CMP=cn-a-j">developerWorks blogs</a>：加入 developerWorks 社区。<br /></li>
		</ul>
<img src ="http://www.blogjava.net/batistuta/aggbug/84333.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/batistuta/" target="_blank">batistuta</a> 2006-11-29 13:36 <a href="http://www.blogjava.net/batistuta/articles/84333.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于session的详细解释 </title><link>http://www.blogjava.net/batistuta/articles/84302.html</link><dc:creator>batistuta</dc:creator><author>batistuta</author><pubDate>Wed, 29 Nov 2006 03:22:00 GMT</pubDate><guid>http://www.blogjava.net/batistuta/articles/84302.html</guid><wfw:comment>http://www.blogjava.net/batistuta/comments/84302.html</wfw:comment><comments>http://www.blogjava.net/batistuta/articles/84302.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/batistuta/comments/commentRss/84302.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/batistuta/services/trackbacks/84302.html</trackback:ping><description><![CDATA[一、术语session 
<p>　　在我的经验里，session这个词被滥用的程度大概仅次于transaction，更加有趣的是transaction与session在某些语境下的含义是相同的。</p><p>　　session，中文经常翻译为会话，其本来的含义是指有始有终的一系列动作/消息，比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。有时候我们可以看到这样的话“在一个浏览器会话期间，...”，这里的会话一词用的就是其本义，是指从一个浏览器窗口打开到关闭这个期间①。最混乱的是“用户（客户端）在一次会话期间”这样一句话，它可能指用户的一系列动作（一般情况下是同某个具体目的相关的一系列动作，比如从登录到选购商品到结账登出这样一个网上购物的过程，有时候也被称为一个transaction），然而有时候也可能仅仅是指一次连接，也有可能是指含义①，其中的差别只能靠上下文来推断②。</p><p>　　然而当session一词与网络协议相关联时，它又往往隐含了“面向连接”和/或“保持状态”这样两个含义，“面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道，比如打电话，直到对方接了电话通信才能开始，与此相对的是写信，在你把信发出去的时候你并不能确认对方的地址是否正确，通信渠道不一定能建立，但对发信人来说，通信已经开始了。“保持状态”则是指通信的一方能够把一系列的消息关联起来，使得消息之间可以互相依赖，比如一个服务员能够认出再次光临的老顾客并且记得上次这个顾客还欠店里一块钱。这一类的例子有“一个TCP session”或者“一个POP3 session”③。</p><p>　　而到了web服务器蓬勃发展的时代，session在web开发语境下的语义又有了新的扩展，它的含义是指一类用来在客户端与服务器之间保持状态的解决方案④。有时候session也用来指这种解决方案的存储结构，如“把xxx保存在session里”⑤。由于各种用于web开发的语言在一定程度上都提供了对这种解决方案的支持，所以在某种特定语言的语境下，session也被用来指代该语言的解决方案，比如经常把Java里提供的 javax.servlet.http.HttpSession简称为session⑥。</p><p>　　鉴于这种混乱已不可改变，本文中session一词的运用也会根据上下文有不同的含义，请大家注意分辨。</p><p>　　在本文中，使用中文“浏览器会话期间”来表达含义①，使用“session机制”来表达含义④，使用“session”表达含义⑤，使用具体的“HttpSession”来表达含义⑥</p><p>　　二、HTTP协议与状态保持</p><p>　　HTTP协议本身是无状态的，这与HTTP协议本来的目的是相符的，客户端只需要简单的向服务器请求<a class="Channel_KeyLink" href="http://www.52z.com/"><font color="#000080">下载</font></a>某些文件，无论是客户端还是服务器都没有必要纪录彼此过去的行为，每一次请求之间都是独立的，好比一个顾客和一个自动售货机或者一个普通的（非会员制）大卖场之间的关系一样。</p><p>　　然而聪明（或者贪心？）的人们很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用，就像给有线电视加上点播功能一样。这种需求一方面迫使HTML逐步添加了表单、脚本、DOM等客户端行为，另一方面在服务器端则出现了CGI规范以响应客户端的动态请求，作为传输载体的HTTP协议也添加了文件上载、cookie这些特性。其中cookie的作用就是为了解决HTTP协议无状态的缺陷所作出的努力。至于后来出现的session机制则是又一种在客户端与服务器之间保持状态的解决方案。</p><p>　　让我们用几个例子来描述一下cookie和session机制之间的区别与联系。笔者曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠，然而一次性消费5杯咖啡的机会微乎其微，这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案：</p><p>　　1、该店的店员很厉害，能记住每位顾客的消费数量，只要顾客一走进咖啡店，店员就知道该怎么对待了。这种做法就是协议本身支持状态。</p><p>　　2、发给顾客一张卡片，上面记录着消费的数量，一般还有个有效期限。每次消费时，如果顾客出示这张卡片，则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。</p><p>　　3、发给顾客一张会员卡，除了卡号之外什么信息也不纪录，每次消费时，如果顾客出示该卡片，则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。</p><p>　　由于HTTP协议是无状态的，而出于种种考虑也不希望使之成为有状态的，因此，后面两种方案就成为现实的选择。具体来说cookie机制采用的是在客户端保持状态的方案，而session机制采用的是在服务器端保持状态的方案。同时我们也看到，由于采用服务器端保持状态的方案在客户端也需要保存一个标识，所以session机制可能需要借助于cookie机制来达到保存标识的目的，但实际上它还有其他选择。</p><p>　　三、理解cookie机制 </p><p>　　cookie机制的基本原理就如上面的例子一样简单，但是还有几个问题需要解决：“会员卡”如何分发；“会员卡”的内容；以及客户如何使用“会员卡”。</p><p>　　正统的cookie分发是通过扩展HTTP协议来实现的，服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。然而纯粹的客户端脚本如JavaScript或者VBScript也可以生成cookie。</p><p>　　而cookie的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的cookie，如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置，则把该cookie附在请求资源的HTTP请求头上发送给服务器。意思是麦当劳的会员卡只能在麦当劳的店里出示，如果某家分店还发行了自己的会员卡，那么进这家店的时候除了要出示麦当劳的会员卡，还要出示这家店的会员卡。</p><p>　　cookie的内容主要包括：名字，值，过期时间，路径和域。</p><p>　　其中域可以指定某一个域比如.google.com，相当于总店招牌，比如宝洁公司，也可以指定一个域下的具体某台机器比如www.google.com或者froogle.google.com，可以用飘柔来做比。</p><p>　　路径就是跟在域名后面的URL路径，比如/或者/foo等等，可以用某飘柔专柜做比。</p><p>　　路径与域合在一起就构成了cookie的作用范围。</p><p>　　如果不设置过期时间，则表示这个cookie的生命期为浏览器会话期间，只要关闭浏览器窗口，cookie就消失了。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里，当然这种行为并不是规范规定的。如果设置了过期时间，浏览器就会把cookie保存到硬盘上，关闭后再次打开浏览器，这些cookie仍然有效直到超过设定的过期时间。</p><p>　　存储在硬盘上的cookie可以在不同的浏览器进程间共享，比如两个IE窗口。而对于保存在内存里的cookie，不同的浏览器有不同的处理方式。对于IE，在一个打开的窗口上按Ctrl-N（或者从文件菜单）打开的窗口可以与原窗口共享，而使用其他方式新开的IE进程则不能共享已经打开的窗口的内存cookie；对于Mozilla Firefox0.8，所有的进程和标签页都可以共享同样的cookie。一般来说是用javascript的window.open打开的窗口会与原窗口共享内存cookie。浏览器对于会话cookie的这种只认cookie不认人的处理方式经常给采用session机制的web应用程序开发者造成很大的困扰。</p><p>　　下面就是一个goolge设置cookie的响应头的例子</p><p>HTTP/1.1 302 Found<br />Location: http://www.google.com/intl/zh-CN/<br />Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com<br />Content-Type: text/html</p>　四、理解session机制 
<p>　session机制是一种服务器端的机制，服务器使用一种类似于散列表的结构（也可能就是使用散列表）来保存信息。</p><p>　　当程序需要为某个客户端的请求创建一个session的时候，服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id，如果已包含一个session id则说明以前已经为此客户端创建过session，服务器就按照session id把这个session检索出来使用（如果检索不到，可能会新建一个），如果客户端请求不包含session id，则为此客户端创建一个session并且生成一个与此session相关联的session id，session id的值应该是一个既不会重复，又不容易被找到规律以仿造的字符串，这个session id将被在本次响应中返回给客户端保存。</p><p>　　保存这个session id的方式可以采用cookie，这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于 SEEESIONID，而。比如weblogic对于web应用程序生成的cookie，JSESSIONID= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764，它的名字就是 JSESSIONID。</p><p>　　由于cookie可以被人为的禁止，必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写，就是把session id直接附加在URL路径的后面，附加方式也有两种，一种是作为URL路径的附加信息，表现形式为http://...../xxx; jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764 另一种是作为查询字符串附加在URL后面，表现形式为http://...../xxx?jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764<br />这两种方式对于用户来说是没有区别的，只是服务器在解析的时候处理的方式不同，采用第一种方式也有利于把session id的信息和正常程序参数区分开来。</p><p>　　为了在整个交互过程中始终保持状态，就必须在每个客户端可能请求的路径后面都包含这个session id。</p><p>　　另一种技术叫做表单隐藏字段。就是服务器会自动修改表单，添加一个隐藏字段，以便在表单提交时能够把session id传递回服务器。比如下面的表单</p><p>&lt;form name="testform" action="/xxx"&gt;<br />&lt;input type="text"&gt;<br />&lt;/form&gt;</p><p>　　在被传递给客户端之前将被改写成</p><p>&lt;form name="testform" action="/xxx"&gt;<br />&lt;input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"&gt;<br />&lt;input type="text"&gt;<br />&lt;/form&gt;</p><p>　　这种技术现在已较少应用，笔者接触过的很古老的iPlanet6(SunONE应用服务器的前身)就使用了这种技术。实际上这种技术可以简单的用对action应用URL重写来代替。</p><p>　　在谈论session机制的时候，常常听到这样一种误解“只要关闭浏览器，session就消失了”。其实可以想象一下会员卡的例子，除非顾客主动对店家提出销卡，否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的，除非程序通知服务器删除一个session，否则服务器会一直保留，程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭，因此服务器根本不会有机会知道浏览器已经关闭，之所以会有这种错觉，是大部分session机制都使用会话cookie来保存session id，而关闭浏览器后这个session id就消失了，再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上，或者使用某种手段改写浏览器发出的 HTTP请求头，把原来的session id发送给服务器，则再次打开浏览器仍然能够找到原来的session。</p><p>　　恰恰是由于关闭浏览器不会导致session被删除，迫使服务器为seesion设置了一个失效时间，当距离客户端上一次使用session的时间超过这个失效时间时，服务器就可以认为客户端已经停止了活动，才会把session删除以节省存储空间。</p><p>　　五、理解javax.servlet.http.HttpSession</p><p>　　HttpSession是Java平台对session机制的实现规范，因为它仅仅是个接口，具体到每个web应用服务器的提供商，除了对规范支持之外，仍然会有一些规范里没有规定的细微差异。这里我们以BEA的Weblogic Server8.1作为例子来演示。</p><p>　　首先，Weblogic Server提供了一系列的参数来控制它的HttpSession的实现，包括使用cookie的开关选项，使用URL重写的开关选项，session持久化的设置，session失效时间的设置，以及针对cookie的各种设置，比如设置cookie的名字、路径、域，cookie的生存时间等。</p><p>　　一般情况下，session都是存储在内存里，当服务器进程被停止或者重启的时候，内存里的session也会被清空，如果设置了 session的持久化特性，服务器就会把session保存到硬盘上，当服务器进程重新启动或这些信息将能够被再次使用，Weblogic Server支持的持久性方式包括文件、数据库、客户端cookie保存和复制。</p><p>　　复制严格说来不算持久化保存，因为session实际上还是保存在内存里，不过同样的信息被复制到各个cluster内的服务器进程中，这样即使某个服务器进程停止工作也仍然可以从其他进程中取得session。</p><p>　　cookie生存时间的设置则会影响浏览器生成的cookie是否是一个会话cookie。默认是使用会话cookie。有兴趣的可以用它来试验我们在第四节里提到的那个误解。</p><p>　　cookie的路径对于web应用程序来说是一个非常重要的选项，Weblogic Server对这个选项的默认处理方式使得它与其他服务器有明显的区别。后面我们会专题讨论。</p><p>　　关于session的设置参考[5] http://e-docs.bea.com/wls/docs70/weba<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>/weblogic_xml.html#1036869</p><p>　　六、HttpSession常见问题</p><p>　　（在本小节中session的含义为⑤和⑥的混合）</p><p>　　1、session在何时被创建</p><p>　　一个常见的误解是以为session在有客户端访问时就被创建，然而事实是直到某server端程序调用 HttpServletRequest.getSession(true)这样的语句时才被创建，注意如果JSP没有显示的使用 &lt;%@page session="false"%&gt; 关闭session，则JSP文件在编译成Servlet时将会自动加上这样一条语句HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的session对象的来历。</p><p>　　由于session会消耗内存资源，因此，如果不打算使用session，应该在所有的JSP中关闭它。</p><p>　　2、session何时被删除</p><p>　　综合前面的讨论，session在下列情况下被删除a.程序调用HttpSession.invalidate();或b.距离上一次收到客户端发送的session id时间间隔超过了session的超时设置;或c.服务器进程被停止（非持久session）</p><p>　　3、如何做到在浏览器关闭时删除session</p><p>　　严格的讲，做不到这一点。可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作，然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力。</p><p>　　4、有个HttpSessionListener是怎么回事</p><p>　　你可以创建这样的listener去监控session的创建和销毁事件，使得在发生这样的事件时你可以做一些相应的工作。注意是 session的创建和销毁动作触发listener，而不是相反。类似的与HttpSession有关的listener还有 HttpSessionBindingListener，HttpSessionActivationListener和 HttpSessionAttributeListener。</p><p>　　5、存放在session中的对象必须是可序列化的吗</p><p>　　不是必需的。要求对象可序列化只是为了session能够在集群中被复制或者能够持久保存或者在必要时server能够暂时把session交换出内存。在Weblogic Server的session中放置一个不可序列化的对象在控制台上会收到一个警告。我所用过的某个iPlanet版本如果session中有不可序列化的对象，在session销毁时会有一个Exception，很奇怪。</p><p>　　6、如何才能正确的应付客户端禁止cookie的可能性</p><p>　　对所有的URL使用URL重写，包括超链接，form的action，和重定向的URL，具体做法参见[6]<br />http://e-docs.bea.com/wls/docs70/weba<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>/sessions.html#100770</p><p>　　7、开两个浏览器窗口访问应用程序会使用同一个session还是不同的session</p><p>　　参见第三小节对cookie的讨论，对session来说是只认id不认人，因此不同的浏览器，不同的窗口打开方式以及不同的cookie存储方式都会对这个问题的答案有影响。</p><p>　　8、如何防止用户打开两个浏览器窗口操作导致的session混乱</p><p>　　这个问题与防止表单多次提交是类似的，可以通过设置客户端的令牌来解决。就是在服务器每次生成一个不同的id返回给客户端，同时保存在 session里，客户端提交表单时必须把这个id也返回服务器，程序首先比较返回的id与保存在session里的值是否一致，如果不一致则说明本次操作已经被提交过了。可以参看《J2EE核心模式》关于表示层模式的部分。需要注意的是对于使用javascript window.open打开的窗口，一般不设置这个id，或者使用单独的id，以防主窗口无法操作，建议不要再window.open打开的窗口里做修改操作，这样就可以不用设置。</p><p>　　9、为什么在Weblogic Server中改变session的值后要重新调用一次session.setValue<br />做这个动作主要是为了在集群环境中提示Weblogic Server session中的值发生了改变，需要向其他服务器进程复制新的session值。</p><p>　　10、为什么session不见了</p><p>　　排除session正常失效的因素之外，服务器本身的可能性应该是微乎其微的，虽然笔者在iPlanet6SP1加若干补丁的Solaris版本上倒也遇到过；浏览器插件的可能性次之，笔者也遇到过3721插件造成的问题；理论上防火墙或者代理服务器在cookie处理上也有可能会出现问题。</p><p>　　出现这一问题的大部分原因都是程序的错误，最常见的就是在一个应用程序中去访问另外一个应用程序。我们在下一节讨论这个问题。</p><p id="#7">　　七、跨应用程序的session共享<br /><br />　　常常有这样的情况，一个大项目被分割成若干小项目开发，为了能够互不干扰，要求每个小项目作为一个单独的web应用程序开发，可是到了最后突然发现某几个小项目之间需要共享一些信息，或者想使用session来实现SSO (single sign on)，在session中保存login的用户信息，最自然的要求是应用程序间能够访问彼此的session。</p><p>　　然而按照Servlet规范，session的作用范围应该仅仅限于当前应用程序下，不同的应用程序之间是不能够互相访问对方的session 的。各个应用服务器从实际效果上都遵守了这一规范，但是实现的细节却可能各有不同，因此解决跨应用程序session共享的方法也各不相同。</p><p>　　首先来看一下Tomcat是如何实现web应用程序之间session的隔离的，从Tomcat设置的cookie路径来看，它对不同的应用程序设置的cookie路径是不同的，这样不同的应用程序所用的session id是不同的，因此即使在同一个浏览器窗口里访问不同的应用程序，发送给服务器的session id也可以是不同的。<br /> 笔者以前用过的iPlanet也采用的是同样的方式，估计SunONE与iPlanet之间不会有太大的差别。对于这种方式的服务器，解决的思路很简单，实际实行起来也不难。要么让所有的应用程序共享一个session id，要么让应用程序能够获得其他应用程序的session id。</p><p>　　iPlanet中有一种很简单的方法来实现共享一个session id，那就是把各个应用程序的cookie路径都设为/（实际上应该是/NASA<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>，对于应用程序来讲它的作用相当于根）。</p><p>&lt;session-info&gt;<br />&lt;path&gt;/NASA<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>&lt;/path&gt;<br />&lt;/session-info&gt;</p><p>　　需要注意的是，操作共享的session应该遵循一些编程约定，比如在session attribute名字的前面加上应用程序的前缀，使得setAttribute("name", "neo")变成setAttribute("a<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>1.name", "neo")，以防止命名空间冲突，导致互相覆盖。</p><p><br />　　在Tomcat中则没有这么方便的选择。在Tomcat版本3上，我们还可以有一些手段来共享session。对于版本4以上的 Tomcat，目前笔者尚未发现简单的办法。只能借助于第三方的力量，比如使用文件、数据库、JMS或者客户端cookie，URL参数或者隐藏字段等手段。</p><p>　　我们再看一下Weblogic Server是如何处理session的。<br /></p><p align="center"><img alt="Session详解" src="http://www.itcnw.com/Article/UploadFiles/200603/20060331183413434.jpg" /></p><p align="center"><img alt="Session详解" src="http://www.itcnw.com/Article/UploadFiles/200603/20060331183413363.jpg" /></p><p>　　从截屏画面上可以看到Weblogic Server对所有的应用程序设置的cookie的路径都是/，这是不是意味着在Weblogic Server中默认的就可以共享session了呢？然而一个小实验即可证明即使不同的应用程序使用的是同一个session，各个应用程序仍然只能访问自己所设置的那些属性。这说明Weblogic Server中的session的内存结构可能如下<br /></p><p align="center"><img alt="Session详解" src="http://www.itcnw.com/Article/UploadFiles/200603/20060331183413923.jpg" /></p><p>　　对于这样一种结构，在session机制本身上来解决session共享的问题应该是不可能的了。除了借助于第三方的力量，比如使用文件、数据库、JMS或者客户端cookie，URL参数或者隐藏字段等手段，还有一种较为方便的做法，就是把一个应用程序的session放到 ServletContext中，这样另外一个应用程序就可以从ServletContext中取得前一个应用程序的引用。示例代码如下，</p><p>　　应用程序A</p><p>context.setAttribute("a<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>A", session); </p><p>　　应用程序B</p><p>contextA = context.getContext("/a<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>A");<br />HttpSession sessionA = (HttpSession)contextA.getAttribute("a<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>A"); </p><p>　　值得注意的是这种用法不可移植，因为根据ServletContext的JavaDoc，应用服务器可以处于安全的原因对于context.getContext("/a<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>A");返回空值，以上做法在Weblogic Server 8.1中通过。</p><p>　　那么Weblogic Server为什么要把所有的应用程序的cookie路径都设为/呢？原来是为了SSO，凡是共享这个session的应用程序都可以共享认证的信息。一个简单的实验就可以证明这一点，修改首先登录的那个应用程序的描述符weblogic.xml，把cookie路径修改为/a<a class="Channel_KeyLink" href="http://www.52z.com/soft/pp.html"><font color="#000080">pp</font></a>A 访问另外一个应用程序会重新要求登录，即使是反过来，先访问cookie路径为/的应用程序，再访问修改过路径的这个，虽然不再提示登录，但是登录的用户信息也会丢失。注意做这个实验时认证方式应该使用FORM，因为浏览器和web服务器对basic认证方式有其他的处理方式，第二次请求的认证不是通过 session来实现的。具体请参看[7] secion 14.8 Authorization，你可以修改所附的示例程序来做这些试验。</p><p>　　八、总结</p><p>　　session机制本身并不复杂，然而其实现和配置上的灵活性却使得具体情况复杂多变。这也要求我们不能把仅仅某一次的经验或者某一个浏览器，服务器的经验当作普遍适用的经验，而是始终需要具体情况具体分析。</p><img src ="http://www.blogjava.net/batistuta/aggbug/84302.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/batistuta/" target="_blank">batistuta</a> 2006-11-29 11:22 <a href="http://www.blogjava.net/batistuta/articles/84302.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Subversion使用手记</title><link>http://www.blogjava.net/batistuta/articles/84012.html</link><dc:creator>batistuta</dc:creator><author>batistuta</author><pubDate>Tue, 28 Nov 2006 04:20:00 GMT</pubDate><guid>http://www.blogjava.net/batistuta/articles/84012.html</guid><wfw:comment>http://www.blogjava.net/batistuta/comments/84012.html</wfw:comment><comments>http://www.blogjava.net/batistuta/articles/84012.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/batistuta/comments/commentRss/84012.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/batistuta/services/trackbacks/84012.html</trackback:ping><description><![CDATA[
		<p>一直以来对于自己的项目都是使用CVS进行管理，听说Subversion很久了，但是都没有时间去尝试。想想时间都是省出来的，于是决定，一天学一点，不多，积累成河嘛。<br />  Subversion和CVS相比，除了包含了CVS的全部特性之外，也加入了新的理念。<br />                                    新理念<br />  1、路径、改名、以及文件meta-data也可进入版本控制范围。<br />  缺少这些特性是CVS被抱怨最多的方面之一，subversion不止对文件内容和文件存放位置加入控制，也对目录，拷贝，重命名操作加入版本控制。它也允许文件/目录的相关元数据meta-data和文件/目录本身一起被版本控制起来，并提供一种机制对文件的执行权限进行控制。<br />  2、Commit动作真正成为原子级的操作了。<br />直到整个commit动作都成功前不会有任何部分的commit会生效。版本修订号只是预确认，而不是对文件预确认。(翻译不出来 -_-;)日志信息将绑定到修订信息，而不是象CVS那样冗余的存储下来。<br /> 3、提供Apache网络服务器选项，支持WebDAV/DeltaV协议。<br />Subversion可以使用基于http协议的WebDAV/DeltaV协议进行网络通讯，并由Apache服务器提供源码仓库方的网络浏览服务。这为Subversion提供了比CVS更好的协同工作能力，并提供了各式各样的自由的关键特性：授权，基于路径的授权，线性压缩，以及基本源码仓库浏览。<br />4、独立服务器选项<br />Subversion也能提供独立服务器选项，使用自定的协议（不是每个人都想运行Apache2.x）独立服务器可以作为系统的inetd服务运行，并提供基本的授权。它也能使用ssh进行加密。<br /> 5、建立<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(4);" onmouseover="kwE(event,4);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://114.vnet.cn/search_web.html?id=148&amp;kw=分支','_blank');" onmouseout="kwL(event);" target="_blank">分支</a></nobr>和标签操作成为不耗时的操作。<br />这些动作没理由耗时，所以我们不再让它们耗时。<br />6、分支与标签的实现都是基于底层的拷贝操作，一个拷贝占用一块固定大小的空间。任何拷贝都可以作为一份标签；假如你开始对某个版本的拷贝进行commit动作，那它也就成为一个分支。(这与CVS的"分支节点做标签"方式不同)<br />7、天然的client/server结构，层次化库设计。<br />Subversion从设计之初即采用client/server机构；因此避免了困扰CVS了许久的一些维护性难题。<br />代码被构建为一组带有详细接口说明的模块，用以方便的由其他应用程序进行调用。<br />8、Client/server协议向双方发送对比差异。<br />网络协议利用宽带有效地发送对比差异给客户端和服务器端双方。( CVS只是 server-&gt;client,?没有client-&gt;server )<br /> 9、资源消耗与数据改变的大小成<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(2);" onmouseover="kwE(event,2);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://114.vnet.cn/search_web.html?id=148&amp;kw=正比','_blank');" onmouseout="kwL(event);" target="_blank">正比</a></nobr>，而不是与数据本身大小成正比一般来说，一项Subversion操作所需时间与操作最终变化的大小成正比。而不是与操作所触及的整个项目的大小成正比，这是Subversion源代码仓库模型的一个特性。<br /> 10、有效的处理二进制文件<br />Subversion对于二进制文件和文本文件的处理同样有效，因为subversion使用一种二进制差异比较算法来增量存储那些连续的修订本。<br /> 11、易于语法分析的输出。<br />所有Subversion命令行客户端的输出都是仔细设计的，可轻松为人所理解，也适于程序自动解析。可进行脚本语言处理将是下一步优先考虑的特性。<br /> 好了，开始使用吧。<br />Subversion到目前的安装已经非常简单了。到Subversion网站下载Windows下的安装文件，简单的步骤就可以完成安装，而且安装程序已经自动注册Path，直接在命令行模式就可以使用了。<br />  首先初始化Repository，输入命令:<br /> svnadmin create D:\TestRepository\<br />然后，把现有的项目的目录结构以及文件导入到Repository中：<br /> svn import D:\Projects\Project1 <a href="file:///D:/TestRepository/Project1"><font color="#000080">file:///D:\TestRepository\Project1</font></a> -m “初始化“<br /> 用启动服务<br /> svnserve -d -r D:\TestRepository\<br /> 客户端Checkout<br /> svn checkout svn://主机名/Project1?? (即获取Project1的项目)<br /> 以上都是很简单的命令。而且上面只用到了一种服务模式，Apache的还在尝试中。<br /> 目前只用到了Subversion的基本功能，就已经感觉不错了，觉得入门很轻松，帮助文档也比CVS要好的多。<br /> Subversion也有图形的客户端，可以在 TortoiseSVN 找到。<br /> Subversion也VS.Net的插件，可以在AnkhSVN 找到。<br /> TortoiseSVN相信不错，因为以前用过它的另一个For CVS的工具，可以和浏览器结合在一起，非常方便和美观。<br />服务<br />    Subversion具有两种服务模式，一个是作为Apache的模块，另一个是自定义协议的Subserve服务。作为Apache的模块，客户端可以通过WebDAV/DeltaV协议访问Repository，而使用Subserve则使用<br />Subversion的自定义协议。<br />下表是两种服务模式的比较：</p>
		<p>
		</p>
		<table class="MsoNormalTable" style="WIDTH: 100%; mso-cellspacing: 0cm; mso-padding-alt: 7.5pt 7.5pt 7.5pt 7.5pt" cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes">
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.32%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">功能<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p> </p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">Apache + mod_dav_sub </span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">Svnserve </span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 1">
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.32%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">验证方式<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">基于<span lang="EN-US">HTTPS</span>的<span lang="EN-US">X.509</span>、<span lang="EN-US">LDAP</span>、<span lang="EN-US">NTLM</span>或其他<span lang="EN-US">Apache</span>支持的验证<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">CRAM-MD5</span>
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">或者<span lang="EN-US">SSH </span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 2">
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.32%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">用户帐户管理<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">私有的用户文件<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">私有的用户文件或已有的系统帐户<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 3">
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.32%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">授权管理<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">blanket read/write access</span>
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">或单一目录的访问控制<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">blanket read/write access </span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 4">
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.32%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">加密<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">可选的<span lang="EN-US">SSL </span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">可选的<span lang="EN-US">SSH</span>隧道<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 5">
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.32%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">交互性<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">可通过支持<span lang="EN-US">WebDAV</span>的客户端访问<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">无交互性<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 6">
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.32%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">Web</span>
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">访问<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">有限的内置支持，或通过第三方的工具，例如<span lang="EN-US">ViewCVS </span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">通过第三方的支持，如<span lang="EN-US">ViewCVS </span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 7">
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.32%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">速度<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">稍慢<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">稍快<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 8; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.32%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">初始安装<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">稍复杂<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
								<td style="BORDER-RIGHT: #d4d0c8; PADDING-RIGHT: 7.5pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 7.5pt; PADDING-BOTTOM: 7.5pt; BORDER-LEFT: #d4d0c8; WIDTH: 33.34%; PADDING-TOP: 7.5pt; BORDER-BOTTOM: #d4d0c8; BACKGROUND-COLOR: transparent" width="33%">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center; mso-pagination: widow-orphan" align="center">
												<span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt; mso-bidi-language: TH">相当简单<span lang="EN-US"></span></span>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
										<p>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<br />                                   启动svnserve服务<br />svnserve 是一个轻量级的服务， 使用自定义的协议通过TCP/IP与<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(1);" onmouseover="kwE(event,1);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://114.vnet.cn/search_web.html?id=148&amp;kw=客户','_blank');" onmouseout="kwL(event);" target="_blank">客户</a></nobr>端通讯。<br />客户端通过由 svn:// 或者 svn+ssh:// 开始的URL访问svnserve服务器。<br />启动服务器<br />端口监控（inetd）模式<br />如果你打算用端口监控来启动处理客户的访问请求的进程，你可以通过传入参数-i来启动：<br />svnserve -i<br />当使用-i参数启动服务的时候，svnserve通过stdin和stdout用自定义协议和客户端<br />通讯。同时服务侦听3690端口。<br />独立端口监控进程<br />使用参数-d启动服务作为一个独立的端口监控进程。<br />svnserve -d<br />当运行svnserve在独立端口监控模式时，你可以使用--listen-port=和--listen-host=参数来自定义需要的端口和主机名称。当前模式默认的端口是3690。<br />当然，也有第三种方法启动svnserve，也就是使用“隧道模式”，使用-t参数启动服务。这个模式要求远程服务程序，如RSH或SSH，已经成功验证用户，并且使用已经校验的用户启动一个属于该用户的svnserve进程。当使用该模式提供服务时，要确认启动的用户帐户具备对Repository的读/写权限。<br />设置项目<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(5);" onmouseover="kwE(event,5);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://114.vnet.cn/search_web.html?id=148&amp;kw=目录','_blank');" onmouseout="kwL(event);" target="_blank">目录</a></nobr><br />当svnserve开始运行时，它将会暴露所有的Repository到网络上。不过，当客户端需要获取一个Repository的内容时，需要指定Reopsitory的绝对<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(0);" onmouseover="kwE(event,0);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://114.vnet.cn/search_web.html?id=148&amp;kw=路径','_blank');" onmouseout="kwL(event);" target="_blank">路径</a></nobr>。例如：一个Repository放在文件路径<br />C:/Project Repository/Project1<br />那么当客户端访问时，需要指定绝对路径：<br />svn://host/C:/Project Repository/Project1<br />所以，为了增加保密性，你可以使用参数-r指定需要暴露的Repository的路径，当用户访问时，只需指定Repository的名称即可。例如上面的Repository，当启动服务时，使用如下的方法：<br />svn -d -r C:/Project Repository<br />那么当客户端访问时，则使用<br />svn://host/Project1<br />就可以获取数据了。<br />内置的验证和授权<br />当客户端连接到一个svnserve进程时，下面的流程就会触发：<br />1、客户选择一个指定的Repository；<br />2、服务处理Repository的配置文件 conf/svnserve.conf文件，并且开始执行在其中定义的所有验证和授权策略；<br />3、依赖与情形和授权策略：<br />a)客户端也许允许匿名访问而不需要验证，或者<br />b)客户但也许需要在任何时候被要求验证，或者<br />c)假如处于"隧道模式"中，客户端将声明自己已经可以被外部验证。<br />很显然，如上所说，用户文件是一个名为svnserve.conf的，放在conf目录下的文件。<br />现在我们来看看如何配置这个文件：<br />这个配置文件放置在Repository的目录中的conf目录下，它有两个节点：<br />[general]<br />[users]<br />其中，[general]的配置信息有：<br />anon-access = read<br />auth-access = write<br />其中表示对于验证有效的以及没通过验证的用户可以做什么事情。分别有read, write和none<br />[users]的<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(3);" onmouseover="kwE(event,3);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://114.vnet.cn/search_web.html?id=148&amp;kw=标签','_blank');" onmouseout="kwL(event);" target="_blank">标签</a></nobr>的配置内容有：<br />USERNAME = PASSWORD<br />password-db = passwd<br />realm = My First Repository<br />其中表示，用户名对应的密码是什么，或者指定一个存储用户名和密码的文件的相对或绝对路径以及指定了Repository的验证领域。如果两个Repository有相同的验证领域，那么它们应该有相同的密码数据库，反之亦然。默认的领域就是指向当前的Repository的路径，与服务器的Repository的根目录相关。</p>
<img src ="http://www.blogjava.net/batistuta/aggbug/84012.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/batistuta/" target="_blank">batistuta</a> 2006-11-28 12:20 <a href="http://www.blogjava.net/batistuta/articles/84012.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>