<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_HeroBeast</title><subtitle type="text">海尔比斯特's Blogs</subtitle><id>http://feed.cnblogs.com/blog/u/15568/rss</id><updated>2012-02-09T02:08:22Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/15568/rss"/><entry><id>http://www.cnblogs.com/HeroBeast/archive/2012/02/09/2343547.html</id><title type="text">腾讯资深产品经理谈敏捷开发于游戏</title><summary type="text">敏捷开发思想谈 敏捷的原则 敏捷开发其实并没有标准型的流程。SCRUM也只是众多衍生体中的一个。实际上就算是SCRUM的实际使用也情况千差万别。所以首先，请大家有这么个概念： 敏捷开发绝对不是一套一成不变的标准化流程。而更多的是一种自适应，自我优化的流程优化理念。 并没有一定的流程，而是需要大家有对任何自己觉得不对的，不正确的...</summary><published>2012-02-09T02:08:00Z</published><updated>2012-02-09T02:08:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2012/02/09/2343547.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2012/02/09/2343547.html"/><content type="html">&lt;p&gt;&lt;strong&gt;敏捷开发思想谈&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 敏捷的原则&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 敏捷开发其实并没有标准型的流程。SCRUM也只是众多衍生体中的一个。实际上就算是SCRUM的实际使用也情况千差万别。所以首先，请大家有这么个概念：   &lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 敏捷开发绝对不是一套一成不变的标准化流程。而更多的是一种自适应，自我优化的流程优化理念。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 并没有一定的流程，而是需要大家有对任何自己觉得不对的，不正确的，效率低下的事情的警觉性，和将之提出来并进一步改正的行动力。 其次，敏捷之于游戏开发，则更要体现&lt;strong&gt;人对游戏本身品质的把握&lt;/strong&gt;，而非对各种文档的审核，这就是和传统软件开发区别最大的地方。 所以，没有最好的流程，只要是合适并且能够持续优化的流程就是好的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 所以：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;不一样的项目经理会有不一样的流程&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;一样的项目经理，不一样的团队，也会有不一样的流程&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;一样的项目经理，一样的团队，每隔一段时间，都还会有不一样的流程。 &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 迭代&lt;/strong&gt;&lt;strong&gt;想与得&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 为什么我们要迭代？&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 进行游戏开发，首先请大家对此铭记于心：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;我们的设计不一定是我们真正想要的&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;文档内容在我们想象中和实际体验版本时的感受不相等&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;我们没法100%&lt;/strong&gt;&lt;strong&gt;的思考到所有需要思考的角落&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 同样，要理解为什么要使用迭代，我们需要明白迭代开发从何而来。最初，软件开发行业中，一般都由需求方提需求，开发方拿到需求开始分析设计，一次性开发成型交付。随着行业的发展，软件复杂度的增大，需求变化的增加，大家发现&lt;strong&gt;一次成型的版本&lt;/strong&gt;往往无法满足需求方的需要，于是返工。当这样的情况多了之后，返工就成了一种标准化的流程，&lt;strong&gt;系统化的返工其实就是我们所谓的迭代&lt;/strong&gt;了。当然这是一种比较民间的解释，但是在游戏产业中，这也说明了：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;迭代的目的是为了应付需求的变化&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 这里的需求变化需要我们的额外注意：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;游戏产业中的需求变化，并非只是指策划或需求方在中途站出来说自己的想法有变。更多的时候，是自己在进行游戏开发的过程中，出于对开发的游戏的认知的加深产生的需求设计的变化。&lt;/strong&gt;一般来说游戏的需求来源于设计，但是&lt;strong&gt;我们的设计却往往并不是我们真实的需求&lt;/strong&gt;。或者说，我们的设计往往不能满足我们真实的需求。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 例如，我们需要一个激烈爽快的单体攻击技能，那么我们的设计可能会涉及到，这个技能的功能，伤害，消耗，动画播放等。这个设计还会涉及到表现：比如技能的动作如何，特效如何，播放速度如何，镜头如何。当我们看到这些设计，我们是否就能确定这些设计能够满足我们的需求？进一步，就算我们看到设计之后，认为能够满足了我们的需求了，但&lt;strong&gt;是否在游戏版本中我们实际体验的时候，实际效果能&lt;/strong&gt;&lt;strong&gt;100%&lt;/strong&gt;&lt;strong&gt;符合我们的预期？&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 当我们清醒地认识到：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;无论我们在设计上花多少时间，我们都无法完全消除设计的实际效果和预期的差距。甚至在超过某种程度之后，我们花在设计上的时间将会形成浪费（这就是所谓的OVER-DESIGN&lt;/strong&gt;&lt;strong&gt;）&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我们就应该开始考虑，什么时候设计应该停止，什么时候我们就应该开始先做，然后预留足够的时间，把那些可能出现的，和必然出现的问题，留给我们后续的迭代来发现和解决。而不是把这些问题试图在一开始全部解决掉，&lt;strong&gt;&lt;u&gt;第一，不现实，第二，不科学。&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 旋转上升&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 什么是迭代&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 那么，迭代究竟是什么？&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 首先要申明一点是，其实我们现在谈论的迭代并不是纯粹的迭代，而是&lt;strong&gt;迭代加增量开发&lt;/strong&gt;。纯粹的迭代是指没有新需求的加入，第一个版本实现的内容就已经完整，之后的版本只是之前内容的优化。而增量，则指下一个版本是在上一个版本基础上增加内容的开发形式。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 那么，迭代加增量开发的意思就显而易见了，而我们需要的开发模式就是这种：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;在不断以版本为基础的增量功能开发的基础上，不断对已经有的功能进行完善和优化。这就是狭义的迭代&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 进一步来讲，广义的迭代，则不仅限于我们的功能开发。而且还要对于我们本身的流程，工具，工作方式，方法，习惯等等&lt;strong&gt;所有可以改变，可以优化的地方进行优化&lt;/strong&gt;，进行修改。最终的目的就是通过一个个版本迭代开发，不只功能品质在变好，团队效率，团队流程等各个方面都会变得越来越好。&lt;strong&gt;最终形成一个真的具有战斗力的团队&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 周期总结会议，以及一系列的问题改正，优化提高事项，以及平时提倡的交流，对于变化的拥抱等等，都是为了这个目标而发生的。所以，&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;&lt;u&gt;敏捷开发是一种精神，而不是一种固定的形式。我们需要有一切都是可以改变的心态和准备，并且真的可以着手去改变任何我们觉得有问题的东西，这样才能真正发挥敏捷迭代开发的优势。&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 陀螺的转动&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 如何迭代&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 迭代的漩涡&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 首先，我们抽象一下，以便大家能简单的明白迭代的形式。迭代就像是一个漩涡，从漩涡中心开始旋转，越转越大。而处于迭代最中心，所有的东西都围绕它来转动的那个核心，就是我们的产品订单（故事清单）。&lt;/p&gt;  &lt;p&gt;&lt;img src="http://djt.open.qq.com/data/attachment/portal/201201/24/184207zzea0eyyb4nky202.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 而那条旋转的线，就是我们的版本。&lt;strong&gt;版本永远围绕着我们的故事清单来开发&lt;/strong&gt;，（故事清单，抽取于我们的游戏的设计），版本总是由故事清单里寻找需要完成的功能，再将根据实际版本得到的反馈，并更新故事清单。&lt;strong&gt;于是功能清单的功能越发的有价值，而版本本身也会越来越有价值&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 迭代的步骤&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 那么，我们的版本该如何围绕我们的功能清单来画这个漩涡？&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 首先，漩涡是一个环绕的圈，所以我们先确定&lt;strong&gt;圈的长度&lt;/strong&gt;：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; 一个迭代的长度&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 在这段固定长度中，&lt;strong&gt;它其实是一条单向封闭线性的线段&lt;/strong&gt;，有始有终。有始有终的过程才能被量化和计划。在线段开始时我们从产品清单中取得信息，在结尾会释放一个版本并向产品订单反馈信息。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 再进一步深入：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 在这线段的开头，我们要从产品订单中取得什么？故事。什么样的故事？&lt;strong&gt;价值（优先级）总和最大，且大小（故事点）&lt;/strong&gt;不超过我们一个周期工作量的故事。仅仅如此么？当然不是，首先，有一个重要的概念：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;&lt;u&gt;系统&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 也许有几个故事隶属于同一个系统下，它们共同组成了这个系统，它们全部完成，或者至少关键部分完成。这个系统才是完整的。&lt;strong&gt;当系统不完整的时候，这些功能的乐趣根本无法体现&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 那么，有可能当我们选择这个周期开发某个高价值功能时，没有开发相应的属于一个系统的其他低价值功能。于是周期末的版本我们发现，&lt;strong&gt;由于系统的不完整&lt;/strong&gt;，这个功能乐趣甚微。如果对这种涉及系统的问题没有认识，那么我们很可能就会对这个高价值功能有错误的认识。 （关于系统理论的知识，请参见WIKI系统学一词）&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 如何避免这个问题？这个时候&lt;strong&gt;人的作用&lt;/strong&gt;就体现出来了。当然我们可以在故事列表上增加一列系统属性，提醒我们。但根本的方法还是&lt;strong&gt;一个或者多个对整个故事列表有着足够把握能力的人来进行掌控&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我们需要有人&lt;strong&gt;能够全面的了解设计意图&lt;/strong&gt;，并且对我们的故事列表进行把关，对我们周期开始的需求选取&lt;strong&gt;进行主导&lt;/strong&gt;。&lt;strong&gt;&lt;u&gt;有一点大家应该明白，规则和标准都是人制定的，那么我们究竟是依靠标准和规则来更好的控制结果，还是依靠人本身？是完善更好的标准，还是培养出更能把握质量的人&lt;/u&gt;&lt;/strong&gt;&lt;u&gt;？&lt;/u&gt;&lt;u&gt;&lt;/u&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 接下来，线段中的开发过程，本质上其实就是分析需求，制定计划，开始开发。或许会周期内分为更细小的周期进行迭代。但是&lt;strong&gt;这些小迭代其实依然是瀑布式开发&lt;/strong&gt;，这点毫无疑问。区别只是在于，这样的小周期内，&lt;strong&gt;我们开发的思想和方针是以敏捷开发的思想为指导的，我们更注重版本，更注重交流，更注重结果。而不是预定义式的开发流程（&lt;/strong&gt;&lt;strong&gt;pre-defined)&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 在线段的结尾，一个周期结束了，我们需要做两件事情，第一是将我们体验版本之后的反馈，反馈回故事清单中。或许我们体验某个功能之后会觉得加上另一个功能会更好玩，于是我们提升这个功能的优先级。或许我们会觉得这个功能很无聊，于是我们把同类型的功能优先级都降低。再或者我们添加，甚至删除一些全新的故事（不推荐）。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 迭代的节奏&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 在迭代中，我们还需要注意我们&lt;strong&gt;迭代的节奏&lt;/strong&gt;，什么时候该松，什么时候该紧。什么时候我们允许大家的发散和更多的思考。什么时候我们应该专注于我们的目标并且忽略其他的一切以得到我们最终的版本。这些都是有所讲究的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 这节奏包括各个方面。那么究竟这样的节奏应该如何来走呢？&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 在一个迭代之内，我们的节奏应该是先松后紧。当然不是说迭代开始时我们的效率可以放缓。这里的先松，是指在一&lt;strong&gt;开始时我们可以有更多的想法和思路&lt;/strong&gt;，更多的探讨和研究。本来我们的迭代工作就是从粗到细，从模糊到精确的进行。在迭代中，我们也如此一步步明确我们的工作。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 一旦目标明确，那么迭代周期SPRINT的名称的含义就出来了：我们向着我们的目标冲刺而去。到了这个阶段，我们需要&lt;strong&gt;收缩我们的讨论和想象，一切以最后的版本和质量为前提&lt;/strong&gt;。以尽可能快的速度来开发我们的功能，提高我们游戏的质量，得到我们需要的结果。至于具体的迭代方式，各有不同，我的方式大家可以参加之前发出的那个VISIO图表。某些细节接下来还会讲到。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 版本&lt;/strong&gt;&lt;strong&gt;持续统一的意志&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 为什么需要版本&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 验证乐趣&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我们的设计在我们的脑海里，很可能和在别人脑海里得到的认识是不一样的。&lt;/p&gt;  &lt;p&gt;或许大家都能有幸得到统一的认识，但是做出来实际体验的时候又不一定能够符合我们的预期。&lt;/p&gt;  &lt;p&gt;就算符合了我们的预期，也许我们玩的时候会发现一些新的点子可以很容易的加入到游戏，并且大幅度的提高游戏性。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 所以，多个迭代版本的目的，首先就是为了：&lt;strong&gt;验证我们的功能是否符合我们的设计预期&lt;/strong&gt;。因为:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;&lt;u&gt;没有实际玩到之前，永远不要相信自己的设计是OK&lt;/u&gt;&lt;/strong&gt;&lt;strong&gt;&lt;u&gt;的&lt;/u&gt;&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我想强调的是，这里的设计预期不仅仅涉及到我们的功能，事实上作为游戏开发，&lt;strong&gt;功能开发永远只占其中的一小部分&lt;/strong&gt;，还有大部分的时间我们需要用来调整，优化，修改，以达到我们的真实预期。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 换一种说法，这里的预期除了功能以外，还有我们对它的感受，也就是&lt;strong&gt;这个功能到底好不好玩&lt;/strong&gt;。而我们关注的重点，也是在好不好玩上。如果只是关注于功能是否完善，那么我们的版本就还离成品有一大段路要走。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 所以迭代版本应该是计划功能均可玩，并且&lt;strong&gt;没有会阻止我们体验所有需要体验内容的&lt;/strong&gt;&lt;strong&gt;BUG&lt;/strong&gt;&lt;strong&gt;的游戏版本&lt;/strong&gt;。它是我们评判一切的依据，因为一切功能，一切资源，一切玩法，&lt;strong&gt;&lt;u&gt;在进入版本可以被我们体验之前，都存在不确定性，只有最后经过版本的体验，这一切的不确定性才能消除。&lt;/u&gt;&lt;/strong&gt;&lt;strong&gt;&lt;u&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 持续集成&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 其次，敏捷开发的要求是快速迭代。但是这里的快速迭代其实远比大家想象的还要快速。或许大家觉得正确的快速迭代就是每一个周期，或2周，或一个月就需要一个版本出来。迭代速度比起传统开发确实快了许多，版本也多了许多。但是事实上的快速迭代远比一个周期要短的多。理想的快速迭代，应该是：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;每个功能，每个改动完成之后都有一个版本能够立即对功能进行验证，进行体验&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 让我们对游戏的改变把握得更直接和高效。&lt;strong&gt;让大部分对游戏方向的修正都发生在开发当中而不仅仅发生在周期的开头或者末尾。&lt;/strong&gt;原因就如我所说，每一个功能从完成，到有乐趣，都需要有一个打磨的过程。在打磨之前，很有可能这个功能根本没有乐趣。所以实际上，我们一周要开发一个功能，很可能我们前4天就需要把功能开发完毕，周四出一个版本进行体验。然后周五针对周四的反馈进行一些BUG修正和反馈修改。之后乐趣才出的来。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 是的，如果是理想情况的话，每一个功能无论大小都应该是这样的一个流程。哪怕是一个只有半天开发周期的功能，我们在3个小时开发后也需要出一个版本对功能进行验证，并提出反馈改进（如果有的话）。之后优化到大家觉得这个功能合格或者有存在的价值之后，我们才会继续下一个功能。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 这样的过程当然过于理想化，每一个功能我们都可以几乎无限的优化下去。所以我们也需要对优化的程度进行取舍。这样取舍的标准还是最终会基于我们开发者自己的个人能力和标准上。更重要的是，我们需要建立每一个功能和变动都需要一个版本进行验证的意识。进而才能追求我们的版本质量和效率。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 冲刺的艺术&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 效率&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 敏捷开发绝对不是牺牲效率追求品质的开发模式。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 相反，在每一个迭代当中：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;效率才是需要追求的第一位&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 唯有在尽可能快地发布版本之后，我们才能根据版本的反馈，进行修正。进而得到更好的版本质量。大部分时候，我们需要的仅仅是以最快的速度得到我们需要的原型。验证我们的设计。 为此我们需要尽可能的追求效率。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 那么，如何得到我们需要的效率？&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 范围&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 首先，&lt;strong&gt;永远不要做多余的事情&lt;/strong&gt;。一旦&lt;strong&gt;目标明确&lt;/strong&gt;，那么我们的目标就是所有我们要做的，在目标范围内的质量优化，必要的代码改善，必要的体验优化，都是可以做的。但是离开了我们目标范围的事情，一件都不要做。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 这里的&lt;strong&gt;范围&lt;/strong&gt;，则是一个度量。而这个度量的划分，则又一次，需要依据我们这些人来判断。它需要我们深刻的理解到，我们&lt;strong&gt;制定这些目标的意义&lt;/strong&gt;，我们要实现的究竟是什么，我们应该优化到什么程度？&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我们有多少时间，那么我们就只能设计到什么程度，做到什么程度。而更多的次要的需求，我们有时间再考虑，更多的兼容性想法我们可以想，前提是我们这个版本还有时间。我们需要画一条基准线，在有限的时间里，我们能做多少内容，该做哪些内容？一切行动都需要以我们的目标为准则。当然，我们还需要考虑量产和下个阶段的准备工作等等（然则，这些其实如果规划的好，应该可以算作这个周期内的目标之一）。但这些都需要服从于当前版本的开发。全力开发我们需要的内容。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 因此&lt;strong&gt;我们需要避免过度设计，过度开发，以及过度优化&lt;/strong&gt;。我们需要将效率作为我们开发的准则。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 人员&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 永远只涉及必要的人&lt;/strong&gt;。为什么我们要进行小组化开发？因为人员牵扯一旦扩大，唯一的结果就是效率降低。各种意见难以统一，管理变得困难，计划难以统筹，任务分配变得困难等等。所以最佳的小组规模应该在7人前后。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 仅仅如此么？当然不是，我们不但要确定小组规模并且将小组开发与外界的干扰屏蔽开。我们还要确定我们项目开发的流程中，每一个步骤所要参与的人员，哪些是真正必须的，哪些是不必参加的。确定人员的职责范围，首先他们需要专心于负责的部分，之后才涉及力所能及的部分。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 在这里，需要解释的一点就是，敏捷开发并&lt;strong&gt;不是所有的决定和步骤都要大家来参与&lt;/strong&gt;，以增进组员责任心和归属感的。为了最大化效率，我们永远&lt;strong&gt;只让必要的人来做必要的事情&lt;/strong&gt;。比如故事分解为任务，只需要小组成员，和相应的主程主美主策。比如故事本身的优先级划分，只需要核心组成员（更加通常的情况是只有PO）参与即可，小组成员没有必要参与。再来，版本体验会，我们需要的是真正的指导性的意见和重要的人的声音，如果需要专门组织一个会来听小组成员对版本的反馈，我觉得那小组成员平时就不知道是干什么去了。我们需要在组织每一场会议的时候都考虑到，是不是每一个到会议的人都是必须到的，因为我们找他来开会的时间，都本来应该是他开发和工作的时间，而那才是我们的重点。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 高效会议&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 最后，我们需要有一个清醒的认识，&lt;strong&gt;过多的会议永远都是高效率的开发的大敌&lt;/strong&gt;。一个会议10个人，一小时，意味着我们会损失10个人时的工作时间。而实际上一周的工作中，我们一个人时都是损失不起的。当然，这并不是意味着我们不要开会。而是我们需要意识到我们的会议究竟是否有必要，如果有，那么会议效率是否足够？我们是否有足够的会议准备和计划，能够保证我们会议的效率？还有我们是否有相应的会议章程，会议时限？这些都是我们需要考虑的，用以高效化会议，减少时间浪费的重要方法。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 所以，当我们思考效率的时候，不妨真的来看看我们现在的开发，分析一下一周的工作中，究竟开发的时间有多少？其他的时间又有多少。看看到底是什么在影响着我们的开发，是否有方法，或者措施，能减弱这些影响。最终进一步加快我们的开发？&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 开发的脉络&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 交流&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 非正式沟通&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 交流，在敏捷开发中，是永远都谈不够的东西。也是永远会存在问题的地方。在敏捷开发中，我们会重视交流而轻文档。原因？只是因为交流永远比文档更高效。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 并非我们就此放弃文档，文档最终会变成记录我们讨论交流结果的工具，便于未来查阅。高效的原因是，在交流的过程中，我们就可以共同修正分歧，修正个人的错误，并且将信息传达给对方。当然，一切都还仅仅是基础的东西。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 进一步的是，究竟&lt;strong&gt;如何能让我们的交流高效？&lt;/strong&gt;首先，必须明确一点，会议并非是高效率交流的良好方式。更好的交流，&lt;strong&gt;应该更多来自于更频繁的，更多的非正式的沟通&lt;/strong&gt;。把所有人拉到一起，强迫他们发言，或者收听，并非能很好的传递信息或者进行讨论。而鼓励他们进行自发的讨论、交流、在每天，在所有的闲暇，都可以进行一些思想，一些想法的发散、讨论。这才是最好的情况。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我们当然也可以就此进行推动。更多的不是人为的设置一些刚性讨论需求，而是制造一种推崇各自讨论的氛围。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 邮件&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 其次，是我们交流的方法。我们有没有真正考虑过，哪些内容我们应该放到正规会议上进行宣讲？哪些内容我们只需要发一封&lt;strong&gt;邮件&lt;/strong&gt;，并收集回信的反馈？哪些内容，我们只需要找到相关的人，非正式地谈论一下就可以得到解决？这些分类一旦清晰，能够为我们的团队节约多少时间？&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 从另一方面来说，有多少内容我们甚至连邮件都没有发出，完全变成了个人的地下行为？在这里，我想强调一下关于邮件的作用，在原来的公司，我们被要求尽量少使用邮件，因为某个时期，员工们甚至把所有需要面谈的内容都用邮件来代替了。距离5米的两个人甚至一周几百封邮件却没有一次谈话。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 而在现在的环境中，邮件却变得相对冷落，很多应该有邮件作为记录，或者应该由邮件发出的内容都借由其他的方式或者没有以任何方式发出。比如现在很多的策划文档，每一次更新，只有一定几率会有邮件通知到大家。比如会议纪要，当然这都还是表现的比较好了。再比如不太重要的设计文档，这些都可以借由邮件发送来让需要知道的人了解，并且相比专门的宣讲会，节约很多的时间。大家只需要看完之后，把反馈意见用邮件发回就可以了。所以，我们可以考虑是否完善我们对于邮件的使用？更重要的是，是否我们可以进一步提高我们对于邮件使用的意识？我相信，这会是一个很漫长的过程，但是必然能够极大提高我们办公的效率。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 其实终究，还是我们考虑问题的方式，我们是否能够意识到我们现在的交流方面的不足，是否能够开始改进？这将是我们是否能够继续成长的关键。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 项目的基石&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 人&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 谈到人，其实就是谈到整个流程和过程中最关键的地方，最关键的元素，也是决定一切事情成败的根本。无论多好的制度，流程，如果没有相应的，合格的人来执行，也只会是失败的结局。那么，在敏捷开发中，或者说在游戏业的敏捷开发中，我们需要什么样的人，我们需要什么样的素质和要求，才能更好的运作这个模式，更好的做，并且做出更好的游戏呢？&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 迭代的意识&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 首先，是&lt;strong&gt;&lt;u&gt;改进&lt;/u&gt;&lt;/strong&gt;的意识。永远记住，没有完美的东西。我们需要保持清醒的认识，认识到我们的项目；我们的流程；我们的文档；我们的游戏等等，都还有可以改进的地方，都还有很多可以改进的地方。改进是没有终点的，我们需要能够找到这些可以改进的地方，我们还需要可以找到改进的方法，并且切实的推行下去。这样，我们才能在一次次迭代中，得到更好的项目，更好的版本，更好的团队，等等。意识到我们有问题，我们才能够改正这些问题。从某种意义上来说，其实这也是&lt;strong&gt;迭代的意识&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 效率的意识&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 其次，我们需要效率的意识，我们要明白，最终，我们是在开发商品。我们是在进行商业运作，所以效率是我们需要真正关心的。而效率的重点并不是每天在公司里花了超过8小时，而是我们的时间是否都真正被有效利用起来了。我们是不是真的在需要的时间内，给出了需要的成品。是否这些成品能够合格。每天做的事情是否有意义，是否能够给予我们的工作和项目帮助？我们是否能够抓住我们&lt;strong&gt;工作的重点&lt;/strong&gt;？而不是浪费在无关痛痒的地方。我们需要考虑我们的工作是否是向着目标前进的，是否足够，是否有效率。要做到效率，我们就需要首先明确我们的目标，其次清醒的意识到我们在做的事情，最后再反省是否有无效或者被浪费的地方。是否我们能做的都做了，是否我们把不需要做的也做了？&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 理解游戏&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 再次，我们需要有&lt;strong&gt;对游戏的把握&lt;/strong&gt;。毕竟，我们做的是游戏，如果做的人都不知道什么是游戏，那么如何能保证我们做出来的游戏能被人喜爱？甚至，我们如何能保证我们做出来的游戏，是游戏， 而不仅仅是一个选择播放的技能地图预览器？所以，首先，我们大家都需要了解游戏，&lt;strong&gt;了解什么是游戏，游戏包含了什么；游戏性是什么；核心玩法是什么；主要模式是什么；画面表现是什么；音效是什么；故事是什么，它们是如何结合的，是如何组合成一个游戏的&lt;/strong&gt;。不同的游戏类型里，这些要素又以什么比例组合，哪一个更加重要。这些都是游戏开发者所需要了解的基本。进而，开发者才能明白，我们现在的游戏已经有了哪些元素，还差哪些元素，已经有的元素是否足够，是否还有所欠缺。这时，合格的游戏开发者们，才有能力说出，我们的开发方向在哪里，应该补充什么元素，有什么欠缺的地方。这样，我们才有能力，做出一个至少完整的游戏。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 开发者的野心&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 进一步，我们如果还有野心，并非只是做一个完整的，良好的游戏，我们还想要有创新，想要做一款让人眼前一亮的游戏。那么我们就不只要了解什么是游戏，我们还需要对游戏有自己的理解和想法，我们需要有自己对这个游戏的未来的想象，并且时常将之拿出来讨论，碰撞，最后留下那些可行的，优秀的方案来实现。我们每个人都需要对我们的游戏有所希望，并且这些希望都是需要时常在我们的大脑里酝酿的。这才是游戏开发最有趣的地方，我们总是可以实现我们脑海中大胆的想法，我们总是可以把我们有趣的意见，点子说出来，如果能够得到大家的赞同，就可以实现到游戏里去。做游戏应该是有趣的，而不是每天重复枯燥无聊的劳动。所以，我们需要思考，并且说出我们的想法。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 快乐地制造快乐&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 用心制造快乐，是不够的，还需快乐地制造快乐&lt;/strong&gt;。让我们并不仅仅是麻木的工作着，而是真的有趣的去做有趣的事。这才是做游戏的本意，这才是大部分人最早加入游戏公司制作游戏的本意。如果我们做的东西连我们自己都无法说服自己，“那是有趣的。”那做出来的真的能有趣么？我们在做游戏，之后才是工作。如果整个游戏，都没有一点自己的心思在里面，那我们就真的只是在勤劳的上下班了。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 而且也只有相互间的思想，想法在碰撞，才会做出有意思的游戏。游戏的设计并不仅仅是策划的事情，游戏的需求也不仅仅是由策划提出。只有大家每个人都可以针对游戏的缺陷，乐趣，玩法能有自己的见解，每天争的面红耳赤，那才是真正做好游戏的取胜之道。在游戏性的讨论上，根本没有策划美术程序之分。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 对游戏工业化开发的把握&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 最后，我们还需要有对游戏开发的把握，对整体的把握。我们是否知道我们现在处于游戏开发的哪个阶段？这个阶段应该重视那些东西？应该注意那些东西？这个阶段我们应该完成那些东西？对于这些我们是否有清醒的认识，清醒的计划？&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我们是否有对我们项目的整体规划？知道我们现在要做什么，知道我们下一步还要做什么，这才能让我们明白我们现在做的是否有意义，是否有效率，是否正确。我们的目的，绝对不是过GR1，2,3,4,5.这一点大家应该明白，我们始终都是在做游戏，如果我们的方法正确，计划正确，那么这些评审对我们产生不了任何影响，那么既然我们每次都需要针对这些评审改变我们的流程计划，那么是不是也意味着我们本身的计划也存在一些问题？这个问题大家也许可以思考一下。不要让问题找到我们，而是我们去寻找问题。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 故事&lt;/strong&gt;&lt;strong&gt;WHY ME? WHY STORY?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 为什么要使用故事？&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我们为什么要使用故事？要理解这个问题，首先要理解故事的作用。那么故事的作用是什么？&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 消除理解误差&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 早期软件开发的需求方往往不懂任何技术，开发者的功能清单却往往难以让需求方有直观的对最后成品的认识。比如，或许一个功能描述是，“战斗场景分为5层可以根据摄像机的移动而相对运动”，但对于非专业人士来说，他们可能无法理解这样的描述意味着什么。于是故事开始发挥了它的作用：以一种大家都认可的方式让所有人对我们要做的功能目标有清楚的认识。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 所以：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;只要能够让全体人充分意识到我们功能开发的目标以及内容，那么它就是一个很好的故事&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 对我们来说，这样的共识需要在策划，美术，程序等人员之间达成，所以我们的故事也需要以一种大家都能理解的方式来表达。而更重要的，不是故事的方式，而是确实所有人都能够完全理解。具体怎么写，其实真的怎么写方便都可以。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 整体统筹估计和管理&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 由于故事是从系统和结构的层面，以一定的高度来描述我们整个项目的框架功能，所以我们可以以较快的速度全面了解我们的功能点，而对于这些功能点，我们还可以进一步快速的给出粗略的估算。进而得出整个项目的大概工期或者每个迭代我们可以完成的故事数量。这里的估算往往是由不准确慢慢到准确的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;每一个周期，每一个项目的历史数据都可以让我们之后的估计更加精确&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 而且这样划分的工作，可以更好的交付给不同的小组完成。小组内部进一步自行组织计划，使得我们的管理工作可以分散到小组，降低管理难度。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 创意管理&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 本质上，&lt;strong&gt;游戏就是已有的同类游戏的完整功能点，加上我们独特的创意&lt;/strong&gt;。完备的前者能让我们的游戏成为一款合格的游戏，而后者的加入则让我们的游戏变得独特。引入故事后，我们可以总是在一个层面，对功能开发和创意尝试的投入进行平衡，相互以取舍。我们可以总是以功能和创意的价值来判断真正对我们有价值的开发顺序。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 故事在讲什么？&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 什么是故事?&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 首先，故事本质上依然是功能点，依然是从需求中抽取出的一个个系统功能。只是以一种所有人都能理解的形式进行描述。所以，为了能够让所有人能够理解，故事仅仅只从实现功能的目的来描述这个功能：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;故事是对功能的目的的描述&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 同时，故事是在讲述这个功能究竟是发挥什么样的作用。所以它本身价值只是简单描述和给予一定参考。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;它不是，不能也不需要详细的描述这个功能的所有细节和玩家对此的感受。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 因为前者有相应的策划文档，后者难以文档化以标准衡量。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 所以，当我们要验收某个故事的时候，并不是我们比照着一个个故事，来体验游戏。看一个个故事是否在游戏中完整的实现了。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 正确的故事验收，应该是在这个故事在组内达成统一之，所有人就应该知道要做成什么样子之后。将单个功能的验收在周期内&lt;/p&gt;  &lt;p&gt;就实时完成。而在最后版本发布之时，对功能进行检验，检测这个功能的最终效果是好还是坏。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我们的目的不只是要看是不是功能A,B,C,D已经完成了，我们应该再深入一步：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;关注于功能是否得到了很好的效果，符合了我们的预期&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;在游戏开发中，则是，是否有了乐趣&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;是否有其他想法，能够让这个游戏更有趣&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 因为仅仅是功能的集合，并不能成为合格的游戏&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 因此，我们也需要改变我们对于设计目的的定义：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;我们的目的并非仅仅是完成某个功能，而是功能能否达到我们需要的乐趣。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 带着这样的思路，我们才能真正的在版本回顾的时候，&lt;strong&gt;给予能够指导我们开发方向的反馈&lt;/strong&gt;，而非仅仅是针对我们功能开发的完整与否，发表意见。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 作为核心组成员，或者，作为整个游戏项目的一员：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;我们不应该仅仅关心于完成情况，各种细小的错误。我们应该看得更远，思考的更远，给予我们的开发真正能提升最终质量的帮助&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 最后，故事包含对它大小的估计，我们可以使用这个估计来对将来的工作和计划进行评估；对它本身价值的估计，让我们在选择他们时可以参考。简单的来说，就是另一些附加的功能。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 用好你的武器&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 如何使用故事&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 故事的来源&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 第一，从已有的游戏设计文档或者框架中&lt;strong&gt;抽取&lt;/strong&gt;的，比如，我们已经知道我们要做的是一个回合制战斗的游戏，那么我们就可以抽取出，基础战斗指令，回合制战斗流程之类的故事。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 第二，&lt;strong&gt;新出现的创意性质的内容&lt;/strong&gt;，比如，今天我突然想到在回合制战斗中加入行动顺序条或许是个很有趣的点子，我告诉大家，大家也觉得这个东西很好，于是我把它加入到清单中。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 第三，当我玩到某个游戏的版本的时候，发现，某个功能给我的反馈不是很好，或者我觉得可以如何改进，&lt;strong&gt;能够让这功能变得更好，那么也可以放进到故事清单中&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 故事的使用&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 首先，我们有一个用来&lt;strong&gt;维护故事的列表&lt;/strong&gt;，术语叫做&lt;strong&gt;产品订单&lt;/strong&gt;，里面罗列了所有我们已经完成或者没有完成，重要的或者不重要的故事。我们可以在里面清楚的看到：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;故事的描述&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;故事点（大小）&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;优先级（价值）&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; l&amp;#160; &lt;strong&gt;当前状态&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 于是，在每个迭代开始的时候，我们都将故事从大到小排列起来，依据上个版本我们能完成的故事量（以故事点来衡量）来&lt;strong&gt;选取我们这个版本需要完成的故事内容&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 故事选取完成后，下一步，则是让整个小组&lt;strong&gt;对故事的内容达成统一&lt;/strong&gt;。也可能只是统一目标，而某些细节在完成的过程中确定。这过程的形式，依然并不固定。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 当大家对故事的内容都有所了解之后，我们可以开始对故事进行分解。&lt;strong&gt;得到相应的详细的任务。任务又成了计划，在对计划进行评估和检验之后，每个周期的工作内容就如此确定&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 故事的作用就基本到此结束，剩下的内容是当单个故事完成的时候，对版本中功能进行体验，如果通过，则这个故事就此完成，最后进行归档之类的收尾工作。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 当然，在故事的具体使用中还有一些细微操作，比如如果一个故事在一个周期中制作时发现比估计的大很多要放到两个周期来做才能完成。那么我们还需要对故事进行拆分之类的操作。这些细微操作还是需要在针对不同的情况进行不同的处理。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 版本体验会&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 当我们一个周期的开发内容完成，每个版本功能都已经在周期内得到了验证，并且已经有了一定的优化。为什么我们还要有一个版本体验会呢？&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 首先，我们每个人负责的领域不同，我们有的人对于美术质量很关注，有的人对于代码质量很关注，有的人对于设计文档很关注。也许我们中的一些人参与了一些功能的开发，但是我们并不能对于这个周期的所有功能，所有的改动有所了解。就算对此有所了解，我们也许也不明白每一个功能的设计用意。最后，&lt;strong&gt;为了让所有人对最终结果达成统一的认识，&lt;/strong&gt;我们需要一个正式的展示会议，向核心组或者高层进行我们这个阶段的成果展示。在展示我们的版本新增功能和内容的同时，核心组也会对这个版本的各个细节和内容进行考察和审核，确定这样的改变是否符合对于游戏性和乐趣的追求，是否符合我们对我们游戏的希望，这样的发展方向是否是正确的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 而在这样的会议中，最重要的是，我们需要得到来自各个方面的反馈。&lt;strong&gt;作为开发者，这可能本身就局限了我们对于我们的版本的认知和看法。&lt;/strong&gt;我们对于我们的版本过于熟悉，有可能自动的忽略掉了一些很重要的问题，或者会错误的认为一些难以被接受的游戏性具有很大的乐趣。而这样的会议，则是指正我们类似问题的恰当时机。针对这些反馈，我们可以更好的修正我们的工作思路和计划。给予我们下一个阶段更好的目标。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 所以，在这里，核心组需要给出的，更多，更重要的，还是对于我们游戏的方向性的，涉及到我们目前开发功能的游戏性和表现上的改进意见或者反馈和一些指导性的意见。因此，我们需要要求我们核心组本身更了解 游戏，更明白游戏性，并且自己对于我们要开发什么样的游戏，有清醒的认识和思考。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 周期总结会&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 自适应，自我优化的流程，需要有两个要素才能真正的进行自我改进。首先最重要的是其中的人要有对流程中的问题，需要优化的地方，甚至是&lt;strong&gt;对优化本身有清醒的认识和意愿&lt;/strong&gt;。其次，就是这样的人&lt;strong&gt;推动的一个优化行动&lt;/strong&gt;。而周期总结会，就是SCRUM中设立的一种针对流程自身优化而进行的一种行为。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 项目总结是游戏业的一个普遍工作习惯，在每一个游戏项目结束的时候，会进行一次全项目级别的总结会议，对于整个项目过程当中，做的好，有典范价值的事物，或者在过程当中发生的有范例价值的问题，甚至是还没有解决的问题进行系统的总结和提炼。之后将之发表，可以成为团队，甚至其他团队&lt;strong&gt;将来工作时的依据和帮助&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 而每一个周期一次的周期总结，则是将这一行为加快，频率加高，在项目进行中不断反复。以此达到&lt;strong&gt;更快速的寻找总结目前我们的优缺点&lt;/strong&gt;，针对我们目前的缺点问题寻找 解决的办法，并且开始行动。总的来说，就是以更快的频率不只是迭代我们的版本，将我们的版本改进的更好。同时也是迭代我们的行为，优化和让我们自己更加的进步。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 其实设立一个这样的会议并不难，每一个周期我们都会有这样的总结会。而会议也总会有这样那样的缺陷和需要优化修改的结果。难的是我们需要切实的推行那些问题的修正措施，难的是我们需要能够直面我们的不足，并且将其提出。我们要能对或许难以开口的问题更直白。&lt;strong&gt;鲁迅先生有云，真正的猛士，敢于直面惨淡的死生。&lt;/strong&gt;我们必须承认我们的工作都是不完善的，都是需要优化的。但是这些问题都不是阻止我们开始修正和改革的借口。敏捷开发的意义也就在于，&lt;strong&gt;知道一开始的我们不足以成功，甚至肯定会出现问题，会有失误&lt;/strong&gt;。但是正是在一次次快速迭代中，我们快速的磨合，快速的修正，最后在一次次的改正与进步中，我们才会得到一个完善的团队，一个良好的流程以及一系列适合我们的方法。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 这也才是周期开发的意义所在。所以，敏捷开发，&lt;strong&gt;并不是一个需要在一开始就有完全的准备的过程，并不是一个需要完整规划，好好考虑的过程&lt;/strong&gt;。我们只需要有一定的东西可以开个头，哪怕还不算成熟，但是我们依然可以在接下来的过程中，对我们的目标愈发的清醒，越发的明确，并且我们本身也会越发的成熟，最终共同达到目标。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 一开始，游戏功能不明确？没问题，我们可以先从知道一定会做的开始做，然后开始探讨我们最后要做的目标，再根据每一个迭代的版本反馈修正我们的目标。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 一开始，我们开发团队磨合不够？没问题，我们可以先让他们从开发简单的底层功能做起，并且同时进行磨合，将磨合过程中需要解决的问题一一提出并改正，最终优化得到一个完善的团队。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 一开始，我们的工具不够？没问题，我们可以先用最快的方式开发原型，同时分析原型制作的方式和需求，进行工具制作。并且在工具可以使用之后，再根据使用者的反馈和项目的进展进一步的优化和改进。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ... ...&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 我们可以做的东西很多，而&lt;strong&gt;那些还没有做的，也同样不能成为我们开始做的障碍&lt;/strong&gt;。&lt;/p&gt;  &lt;p&gt;原文：&lt;a href="http://djt.open.qq.com/portal.php?mod=view&amp;amp;aid=115"&gt;http://djt.open.qq.com/portal.php?mod=view&amp;amp;aid=115&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2343547.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2012/02/09/2343547.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/HeroBeast/archive/2011/12/20/2295021.html</id><title type="text">js矢量图类库：Rapha&amp;euml;l&amp;mdash;JavaScript Library</title><summary type="text">官方网址：http://raphaeljs.com/ Rapha&amp;#235;l is a small JavaScript library that should simplify your work with vector graphics on the web. If you want to create your own specific chart or image crop and rotate...</summary><published>2011-12-20T10:23:00Z</published><updated>2011-12-20T10:23:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2011/12/20/2295021.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2011/12/20/2295021.html"/><content type="html">&lt;p&gt;官方网址：&lt;a title="http://raphaeljs.com/" href="http://raphaeljs.com/"&gt;http://raphaeljs.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Raphaël is a small JavaScript library that should simplify your work with vector graphics on the web. If you want to create your own specific chart or image crop and rotate widget, for example, you can achieve it simply and easily with this library. &lt;/p&gt;  &lt;p&gt;Raphaël ['ræfeɪəl] uses the &lt;abbr&gt;SVG&lt;/abbr&gt; &lt;abbr&gt;W3C&lt;/abbr&gt; Recommendation and &lt;abbr&gt;VML&lt;/abbr&gt; as a base for creating graphics. This means every graphical object you create is also a &lt;abbr&gt;DOM&lt;/abbr&gt; object, so you can attach JavaScript event handlers or modify them later. Raphaël’s goal is to provide an adapter that will make drawing vector art compatible cross-browser and easy. &lt;/p&gt;  &lt;p&gt;Raphaël currently supports Firefox 3.0+, Safari 3.0+, Chrome 5.0+, Opera 9.5+ and Internet Explorer 6.0+. &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;最近在做一个关于客户与品牌，客户与代理关系的展示，由于用二维表展示不是很直观，所以就想做个比较直观的，在网上搜到了Raphael，就小试了一下，感觉不错；&lt;/p&gt;  &lt;p&gt;下面是试用结果截图：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/HeroBeast/201112/20111220182318633.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/HeroBeast/201112/201112201823193490.png" width="448" height="429" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/HeroBeast/201112/201112201823198257.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/HeroBeast/201112/20111220182320242.png" width="494" height="209" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;源码如下：&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;pre&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; data = {&#xD;
                   &amp;quot;&lt;span style="color: #8b0000"&gt;customer&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;方正电子&lt;/span&gt;&amp;quot;,&#xD;
                   &amp;quot;&lt;span style="color: #8b0000"&gt;brands&lt;/span&gt;&amp;quot;:&#xD;
                   [&#xD;
   		            { &amp;quot;&lt;span style="color: #8b0000"&gt;brand&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;经略广告&lt;/span&gt;&amp;quot; },&#xD;
   		            { &amp;quot;&lt;span style="color: #8b0000"&gt;brand&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;文韬采编&lt;/span&gt;&amp;quot; },&#xD;
   		            { &amp;quot;&lt;span style="color: #8b0000"&gt;brand&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;飞腾创艺&lt;/span&gt;&amp;quot; },&#xD;
   		            { &amp;quot;&lt;span style="color: #8b0000"&gt;brand&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;畅享全媒体&lt;/span&gt;&amp;quot; }&#xD;
   	            ]&#xD;
               };&#xD;
&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; r = Raphael(&amp;quot;&lt;span style="color: #8b0000"&gt;holder&lt;/span&gt;&amp;quot;, 500, 500);&#xD;
               angle = 0;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; interval = 36;&#xD;
               &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (data != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; data.brands.&lt;span style="color: #0000ff"&gt;length&lt;/span&gt; &amp;gt; 0) {&#xD;
                   &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (data.brands.&lt;span style="color: #0000ff"&gt;length&lt;/span&gt; &amp;lt; 13) {&#xD;
                       interval = 360 / data.brands.&lt;span style="color: #0000ff"&gt;length&lt;/span&gt;;&#xD;
                   }&#xD;
&#xD;
               }&#xD;
&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; centerX = 250;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; centerY = 250;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; mc = Raphael.getColor();&#xD;
               mc = Raphael.getColor();&#xD;
               &lt;span style="color: #008000"&gt;// mc = Raphael.getColor();&lt;/span&gt;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; index = 0;&#xD;
               &lt;span style="color: #0000ff"&gt;while&lt;/span&gt; (angle &amp;lt; 360) {&#xD;
                   &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; color = Raphael.getColor();&#xD;
&#xD;
                   (&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (t, c) {&#xD;
                       r.circle(centerX, 400, 50).attr({ stroke: c, fill: c, transform: t, &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .4 }).click(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
&#xD;
                       }).mouseover(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
                           &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.animate({ &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .95 }, 500);&#xD;
                       }).mouseout(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
                           &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.animate({ &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .4 }, 500);&#xD;
                       });&#xD;
&#xD;
                   })(&amp;quot;&lt;span style="color: #8b0000"&gt;r&lt;/span&gt;&amp;quot; + angle + &amp;quot;&lt;span style="color: #8b0000"&gt; &lt;/span&gt;&amp;quot; + centerX + &amp;quot;&lt;span style="color: #8b0000"&gt; &lt;/span&gt;&amp;quot; + centerY + &amp;quot;&lt;span style="color: #8b0000"&gt;&lt;/span&gt;&amp;quot;, color);&#xD;
&#xD;
&#xD;
                   &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; path_transform = &amp;quot;&lt;span style="color: #8b0000"&gt;r&lt;/span&gt;&amp;quot; + angle + &amp;quot;&lt;span style="color: #8b0000"&gt; &lt;/span&gt;&amp;quot; + centerX + &amp;quot;&lt;span style="color: #8b0000"&gt; &lt;/span&gt;&amp;quot; + centerY + &amp;quot;&lt;span style="color: #8b0000"&gt;&lt;/span&gt;&amp;quot;;&#xD;
                   r.path(&amp;quot;&lt;span style="color: #8b0000"&gt;M&lt;/span&gt;&amp;quot; + centerX + &amp;quot;&lt;span style="color: #8b0000"&gt;,&lt;/span&gt;&amp;quot; + centerY + &amp;quot;&lt;span style="color: #8b0000"&gt;L&lt;/span&gt;&amp;quot; + centerX + &amp;quot;&lt;span style="color: #8b0000"&gt;,350z&lt;/span&gt;&amp;quot;).attr({ stroke: mc, fill: mc, transform: path_transform + &amp;quot;&lt;span style="color: #8b0000"&gt;,&lt;/span&gt;&amp;quot; + mc, &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .4 });&#xD;
                   &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; brandName = r.text(centerX, 400, data.brands[index].brand).attr({&#xD;
                       font: '16px Arial',&#xD;
                       fill: '#000',&#xD;
                       transform: path_transform + &amp;quot;&lt;span style="color: #8b0000"&gt;,&lt;/span&gt;&amp;quot; + mc&#xD;
                   }).toFront();&#xD;
                   brandName.rotate(0 - angle, brandName.x, brandName.y);&#xD;
&#xD;
&#xD;
&#xD;
                   index++;&#xD;
                   angle += interval;&#xD;
               }&#xD;
&#xD;
&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; s = r.set();&#xD;
&#xD;
               s.push(r.circle(centerX, centerY, 60));&#xD;
&#xD;
&#xD;
               s.attr({ stroke: mc, fill: mc })&#xD;
&#xD;
               .mouseover(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
                   &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.animate({ &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: 1.75 }, 500);&#xD;
               }).mouseout(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
                   &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.animate({ &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: 1 }, 500);&#xD;
               });&#xD;
               s.push(r.text(centerX, centerY, data.customer).attr({ font: '16px Arial', fill: '#fff' }));&lt;/pre&gt;&#xD;
&#xD;
&lt;pre&gt;&lt;span style="color: #0000ff"&gt;var&lt;/span&gt; data = {&#xD;
                   &amp;quot;&lt;span style="color: #8b0000"&gt;customer&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;联想集团&lt;/span&gt;&amp;quot;,&#xD;
                   &amp;quot;&lt;span style="color: #8b0000"&gt;agents&lt;/span&gt;&amp;quot;:&#xD;
                   [&#xD;
   		            { &amp;quot;&lt;span style="color: #8b0000"&gt;agent&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;中关村在线&lt;/span&gt;&amp;quot; },&#xD;
   		            { &amp;quot;&lt;span style="color: #8b0000"&gt;agent&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;苏宁电器&lt;/span&gt;&amp;quot; },&#xD;
                       { &amp;quot;&lt;span style="color: #8b0000"&gt;agent&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;国美电器&lt;/span&gt;&amp;quot; },&#xD;
                       { &amp;quot;&lt;span style="color: #8b0000"&gt;agent&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;京东商城&lt;/span&gt;&amp;quot; },&#xD;
   		            { &amp;quot;&lt;span style="color: #8b0000"&gt;agent&lt;/span&gt;&amp;quot;: &amp;quot;&lt;span style="color: #8b0000"&gt;淘宝商城&lt;/span&gt;&amp;quot; }&#xD;
   	            ]&#xD;
               };&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; containerW = 500;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; containerH = 500;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; r = Raphael(&amp;quot;&lt;span style="color: #8b0000"&gt;holder&lt;/span&gt;&amp;quot;, containerW, containerH);&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; boxW = 70; &lt;span style="color: #008000"&gt;//方框宽度&lt;/span&gt;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; boxH = 30;  &lt;span style="color: #008000"&gt;//方框高度&lt;/span&gt;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; subBoxY = 150; &lt;span style="color: #008000"&gt;//代理框的y坐标&lt;/span&gt;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; paddingY = 10; &lt;span style="color: #008000"&gt;//图的内边距 &lt;/span&gt;&#xD;
&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; angle = 0;&#xD;
&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; interval = 10;&#xD;
               &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (data != &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; data.agents.&lt;span style="color: #0000ff"&gt;length&lt;/span&gt; &amp;gt; 0) {&#xD;
                   &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; ((&lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(boxW, 10) * data.agents.&lt;span style="color: #0000ff"&gt;length&lt;/span&gt;) &amp;lt; containerW) {&#xD;
                       &lt;span style="color: #008000"&gt;//间隔=（containerW-代理个数*boxW)/代理个数+1）&lt;/span&gt;&#xD;
                       interval = ((&lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(containerW, 10) - (&lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(boxW, 10) * data.agents.&lt;span style="color: #0000ff"&gt;length&lt;/span&gt;)) / (data.agents.&lt;span style="color: #0000ff"&gt;length&lt;/span&gt; + 1));&#xD;
                   }&#xD;
&#xD;
               }&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; mainColor = Raphael.getColor();&#xD;
               mainColor = Raphael.getColor();&#xD;
               &lt;span style="color: #008000"&gt;//画当前客户框&lt;/span&gt;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; mainBoxX = ((&lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(containerW, 10) - &lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(boxW, 10)) / 2);&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; mainBox = r.rect(mainBoxX, paddingY, boxW, boxH).attr({ stroke: mainColor, fill: mainColor, &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .4 })&#xD;
               .mouseover(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
                       &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.animate({ &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .95 }, 500);&#xD;
                   }).mouseout(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
                       &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.animate({ &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .4 }, 500);&#xD;
                   });&#xD;
                   &lt;span style="color: #008000"&gt;//写客户名称&lt;/span&gt;&#xD;
                   r.text(mainBoxX+(boxW/2), paddingY+(boxH/2), data.customer).attr({ font: '12px Arial', fill: '#fff' })&#xD;
               &lt;span style="color: #008000"&gt;//画中间横线&lt;/span&gt;&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; mX = (interval + ((&lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(boxW, 10) / 2)));&#xD;
               &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; mY = ((&lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(subBoxY, 10) - &lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(paddingY, 10) - &lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(boxH, 10)) / 2) + &lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(paddingY, 10) + &lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(boxH, 10);&#xD;
               r.path(Raphael.format(&amp;quot;&lt;span style="color: #8b0000"&gt;M{0},{1}L{2},{3}z&lt;/span&gt;&amp;quot;,&#xD;
               mX,&#xD;
               mY,&#xD;
               (containerW - mX),&#xD;
                mY));&#xD;
&#xD;
               &lt;span style="color: #008000"&gt;//画当前客户和横线的连接线&lt;/span&gt;&#xD;
               r.path(Raphael.format(&amp;quot;&lt;span style="color: #8b0000"&gt;M{0},{1}L{2},{3}z&lt;/span&gt;&amp;quot;,&#xD;
               (&lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(containerW, 10)/2),&#xD;
               mY,&#xD;
               (&lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(containerW, 10) / 2),&#xD;
                &lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(paddingY, 10) + &lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(boxH, 10)));&#xD;
&#xD;
               angle = interval;&#xD;
               $.each(data.agents, &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (i) {&#xD;
                   &lt;span style="color: #008000"&gt;//生成多个代理框&lt;/span&gt;&#xD;
                   &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; color = Raphael.getColor();&#xD;
&#xD;
                   &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; box1 = r.rect(angle, subBoxY, boxW, boxH).attr({ stroke: color, fill: color, &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .4 }).click(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
&#xD;
                   }).mouseover(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
                       &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.animate({ &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .95 }, 500);&#xD;
                   }).mouseout(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&#xD;
                       &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.animate({ &amp;quot;&lt;span style="color: #8b0000"&gt;fill-opacity&lt;/span&gt;&amp;quot;: .4 }, 500);&#xD;
                   });&#xD;
                   &lt;span style="color: #008000"&gt;//画线&lt;/span&gt;&#xD;
                   r.path(Raphael.format(&amp;quot;&lt;span style="color: #8b0000"&gt;M{0},{1}L{2},{3}z&lt;/span&gt;&amp;quot;,&#xD;
                   (angle+(boxW/2)),&#xD;
                   subBoxY,&#xD;
                   (angle+(boxW/2)),&#xD;
                   mY));&#xD;
                   &lt;span style="color: #008000"&gt;//写代理名称&lt;/span&gt;&#xD;
                   r.text(angle + (boxW / 2), subBoxY + (boxH / 2), data.agents[i].agent).attr({ font: '12px Arial', fill: '#fff' })&#xD;
                   angle += &lt;span style="color: #0000ff"&gt;parseInt&lt;/span&gt;(boxW, 10) + interval;&#xD;
               });&lt;/pre&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2295021.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2011/12/20/2295021.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/HeroBeast/archive/2011/12/09/2282280.html</id><title type="text">关于生成id的问题</title><summary type="text">表明 表最大id 方法1： GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROCEDURE [dbo].[getserial] @serialname char(30) ASbegindeclare @serialno...</summary><published>2011-12-09T07:18:00Z</published><updated>2011-12-09T07:18:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2011/12/09/2282280.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2011/12/09/2282280.html"/><content type="html">&lt;table border="0" cellspacing="0" cellpadding="2" width="185"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="67"&gt;表明&lt;/td&gt;        &lt;td valign="top" width="116"&gt;表最大id&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="67"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="116"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;方法1：&lt;/p&gt;  &lt;pre &gt;&lt;span style="color: blue"&gt;GO&#xD;
&lt;/span&gt;&lt;span style="color: blue"&gt;SET ANSI_NULLS ON&#xD;
GO&#xD;
SET QUOTED_IDENTIFIER ON&#xD;
GO&#xD;
ALTER PROCEDURE &lt;/span&gt;&lt;span style="color: teal"&gt;[dbo]&lt;/span&gt;&lt;span style="color: gray"&gt;.&lt;/span&gt;&lt;span style="color: teal"&gt;[getserial] @serialname &lt;/span&gt;&lt;span style="color: blue"&gt;char&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;30&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;AS&#xD;
begin&#xD;
declare &lt;/span&gt;&lt;span style="color: teal"&gt;@serialno &lt;/span&gt;&lt;span style="color: blue"&gt;int&#xD;
begin transaction&#xD;
select &lt;/span&gt;&lt;span style="color: teal"&gt;@serialno &lt;/span&gt;&lt;span style="color: gray"&gt;= &lt;/span&gt;&lt;span style="color: teal"&gt;SV_nSerial &lt;/span&gt;&lt;span style="color: blue"&gt;from &lt;/span&gt;&lt;span style="color: teal"&gt;SystemVariable &lt;/span&gt;&lt;span style="color: blue"&gt;with&lt;/span&gt;&lt;span style="color: gray"&gt;(&lt;/span&gt;&lt;span style="color: blue"&gt;TABLOCKX HOLDLOCK&lt;/span&gt;&lt;span style="color: gray"&gt;) &lt;/span&gt;&lt;span style="color: blue"&gt;where &lt;/span&gt;&lt;span style="color: teal"&gt;SV_strName &lt;/span&gt;&lt;span style="color: gray"&gt;= &lt;/span&gt;&lt;span style="color: teal"&gt;@serialname&#xD;
&lt;/span&gt;&lt;span style="color: blue"&gt;if &lt;/span&gt;&lt;span style="color: teal"&gt;@serialno &lt;/span&gt;&lt;span style="color: gray"&gt;is null&#xD;
&lt;/span&gt;&lt;span style="color: blue"&gt;begin&#xD;
commit&#xD;
raiserror &lt;/span&gt;50010 &lt;span style="color: red"&gt;'SystemVariable lack record'&#xD;
&lt;/span&gt;&lt;span style="color: blue"&gt;end&#xD;
else&#xD;
begin&#xD;
update &lt;/span&gt;&lt;span style="color: teal"&gt;SystemVariable &lt;/span&gt;&lt;span style="color: blue"&gt;set &lt;/span&gt;&lt;span style="color: teal"&gt;SV_nSerial &lt;/span&gt;&lt;span style="color: gray"&gt;= &lt;/span&gt;&lt;span style="color: teal"&gt;@serialno&lt;/span&gt;&lt;span style="color: gray"&gt;+&lt;/span&gt;1 &lt;span style="color: blue"&gt;where &lt;/span&gt;&lt;span style="color: teal"&gt;SV_strName &lt;/span&gt;&lt;span style="color: gray"&gt;= &lt;/span&gt;&lt;span style="color: teal"&gt;@serialname&#xD;
&lt;/span&gt;&lt;span style="color: blue"&gt;commit&#xD;
select &lt;/span&gt;&lt;span style="color: teal"&gt;@serialno&lt;/span&gt;&lt;span style="color: gray"&gt;+&lt;/span&gt;1&#xD;
&lt;span style="color: blue"&gt;end&#xD;
end&#xD;
&lt;/span&gt;&lt;/pre&gt;&#xD;
s&#xD;
&#xD;
&lt;p&gt;方法2：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span style="color: blue"&gt;declare &lt;/span&gt;&lt;span style="color: teal"&gt;@max &lt;/span&gt;&lt;span style="color: blue"&gt;int&#xD;
select &lt;/span&gt;&lt;span style="color: teal"&gt;@max &lt;/span&gt;&lt;span style="color: gray"&gt;= &lt;/span&gt;&lt;span style="color: teal"&gt;SV_nSerial &lt;/span&gt;&lt;span style="color: blue"&gt;from &lt;/span&gt;&lt;span style="color: teal"&gt;SystemVariable &lt;/span&gt;&lt;span style="color: blue"&gt;where &lt;/span&gt;&lt;span style="color: teal"&gt;SV_strName &lt;/span&gt;&lt;span style="color: gray"&gt;= &lt;/span&gt;&lt;span style="color: teal"&gt;@serialname&#xD;
&#xD;
&lt;/span&gt;&lt;span style="color: blue"&gt;update &lt;/span&gt;&lt;span style="color: teal"&gt;SystemVariable &lt;/span&gt;&lt;span style="color: blue"&gt;set &lt;/span&gt;&lt;span style="color: teal"&gt;SV_nSerial &lt;/span&gt;&lt;span style="color: gray"&gt;= &lt;/span&gt;&lt;span style="color: teal"&gt;@max&lt;/span&gt;&lt;span style="color: gray"&gt;+&lt;/span&gt;1 &lt;span style="color: blue"&gt;where &lt;/span&gt;&lt;span style="color: teal"&gt;SV_strName &lt;/span&gt;&lt;span style="color: gray"&gt;= &lt;/span&gt;&lt;span style="color: teal"&gt;@serialname &lt;/span&gt;&lt;span style="color: gray"&gt;and &lt;/span&gt;&lt;span style="color: teal"&gt;SV_nSerial &lt;/span&gt;&lt;span style="color: gray"&gt;= &lt;/span&gt;&lt;span style="color: teal"&gt;@max&lt;/span&gt;&lt;/pre&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2282280.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2011/12/09/2282280.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/HeroBeast/archive/2011/11/21/2257293.html</id><title type="text">SSL为Windows server 2008 IIS7进行加密连接</title><summary type="text">运行“Internet信息服务(IIS)管理器”，单击服务器名字：ITPUB个人空间WV@dv:`9A~LPj 双击中间栏内的“服务器证书”:ITPUB个人空间!e$A^3I1t4e3s 在“服务器证书”的右栏内单击“创建自签名证书”：ITPUB个人空间jP6wP/db E 为创建的自签名证书指定一个好记名称。 回到“Internet信息服务(IIS)管理器”单...</summary><published>2011-11-21T07:45:00Z</published><updated>2011-11-21T07:45:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2011/11/21/2257293.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2011/11/21/2257293.html"/><content type="html">&lt;p&gt;运行“Internet信息服务(IIS)&lt;a href="http://space.itpub.net/"&gt;&lt;u&gt;&lt;strong&gt;管理&lt;/strong&gt;&lt;/u&gt;&lt;/a&gt;器”，单击服务器名字：ITPUB个人空间WV@dv:`9A~LPj    &lt;br /&gt;&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/200852415585.jpg" width="495" height="369" /&gt;&lt;/p&gt;  &lt;p&gt;双击中间栏内的“服务器证书”:ITPUB个人空间!e$A^3I1t4e3s   &lt;br /&gt;&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/2008524155829.jpg" width="498" height="372" /&gt;&lt;/p&gt;  &lt;p&gt;在“服务器证书”的右栏内单击“创建自签名证书”：ITPUB个人空间jP6wP/db E   &lt;br /&gt;&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/2008524155841.jpg" width="496" height="350" /&gt;&lt;/p&gt;  &lt;p&gt;为创建的自签名证书指定一个好记名称。&lt;/p&gt;  &lt;p&gt;回到“Internet信息服务(IIS)管理器”单击想要进行SSL加密连接的网站:   &lt;br /&gt;WZia'}jZ/E_ L0&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/200852415590.jpg" width="493" height="368" /&gt;&lt;/p&gt;  &lt;p&gt;单击“绑定...&amp;quot;,弹出网站绑定对话框:   &lt;br /&gt;c_ q2bf0&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/2008524155914.jpg" width="468" height="179" /&gt;&lt;/p&gt;  &lt;p&gt;单击“添加...”按钮弹出“添加网站绑定”对话框：   &lt;br /&gt;z#acJ {bB0&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/2008524155926.jpg" width="399" height="199" /&gt;&lt;/p&gt;  &lt;p&gt;在对话框中的配置如上图。IP地址：选择你的服务器IP地址，SSL证书是刚才创建的“自签名证书”。&lt;/p&gt;  &lt;p&gt;可以看到已绑定的网站：   &lt;br /&gt;&amp;quot;E3PlrsF,yz0&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/2008524155941.jpg" width="465" height="178" /&gt;&lt;/p&gt;  &lt;p&gt;打开浏览器，在地址栏内输入：&lt;a href="https://192.168.0.117/"&gt;https://192.168.0.117&lt;/a&gt;，当打开网站时会弹出如下提示：客户端浏览器由于不能辨别证书的合法性，所以提出警告，并给出三个选择：ITPUB个人空间4sx(\9?|`5Y:M    &lt;br /&gt;&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/2008524155957.jpg" width="498" height="322" /&gt;&lt;/p&gt;  &lt;p&gt;选择第二个选项。&lt;/p&gt;  &lt;p&gt;再次提出安全警告，怀疑安全证书不可靠：   &lt;br /&gt;)H6X&amp;amp;@r'rQ Ec^^0&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/20085241609.jpg" width="381" height="180" /&gt;&lt;/p&gt;  &lt;p&gt;点击“确定”按钮，加密连接到IIS服务器:ITPUB个人空间`Q&amp;amp;^iVa N H   &lt;br /&gt;&lt;img title="点击图片可在新窗口打开" alt="" src="http://image.it168.com/cms/2008-5-24/Image/200852416023.jpg" width="499" height="529" /&gt;&lt;/p&gt;  &lt;p&gt;这只是其中的一种方法。和Windowsserver2003相比，配置要简单些，图形化界面。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2257293.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2011/11/21/2257293.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/HeroBeast/archive/2011/11/18/2253489.html</id><title type="text">详解HTML</title><summary type="text">1. 详解HTML 标签和属性 在HTML中，通常标签都是由开始标签和结束标签组成的，开始标签用“&amp;lt;标签名&amp;gt;”表示，结束标签用“&amp;lt;/标签名&amp;gt;”表示。 元素指的是包含标签在内的整体，除去标签的部分叫做内容。 属性要在开始标签中指定，用来表示该标签的性质和特性。通常都是以“属性名=”值””的形式来表示，用空格隔开后，还可以指定多个属性。指定多个属性时不用区分顺序 颜色的指定方法 用HTML...</summary><published>2011-11-18T01:20:00Z</published><updated>2011-11-18T01:20:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2011/11/18/2253489.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2011/11/18/2253489.html"/><content type="html">&lt;p&gt;&lt;strong&gt;1. 详解HTML&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;标签和属性&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在HTML中，通常标签都是由开始标签和结束标签组成的，开始标签用“&amp;lt;标签名&amp;gt;”表示，结束标签用“&amp;lt;/标签名&amp;gt;”表示。&lt;/p&gt;  &lt;p&gt;元素指的是包含标签在内的整体，除去标签的部分叫做内容。&lt;/p&gt;  &lt;p&gt;属性要在开始标签中指定，用来表示该标签的性质和特性。通常都是以“属性名=”值””的形式来表示，用空格隔开后，还可以指定多个属性。指定多个属性时不用区分顺序&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;颜色的指定方法&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;用HTML指定颜色有两种方法&lt;/p&gt;  &lt;p&gt;1、用16进制数值来指定：在#号的后面，把RGB的各个选项用十六进制的数值来表示，数值保持两位数。&lt;/p&gt;  &lt;p&gt;2、指定颜色的名称：可以对基本的16色用名称来指定其颜色&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;指定文件的位置&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在对某部分设置链接的时候，需要指定链接端HTML文件的位置；同样，如果想在该处显示图像也需要指定图像的位置。在HTML中，这个位置用URL来表示，有以下两种表示方法：&lt;/p&gt;  &lt;p&gt;1、绝对URL：绝对URL就是用Web浏览器查看网页时，地址栏中显示的以http://开头的路径&lt;/p&gt;  &lt;p&gt;2、相对URL：相对URL是在同一站点内进行设置，类似于在同一磁盘上管理文件的形式。这种方法是以当前文件的位置为基准。使用相对URL时，如果要指定的文件在当前文件的下级，就从目录名开始一直写到要指定的文件名，中间用“/”符号隔开。如果在当前文件的上级，每上一级就加一个“../”符号&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;strong&gt;、基本内容&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;显示HTML&lt;/strong&gt;&lt;strong&gt;的版本&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;!DOCTYPE~&amp;gt;&lt;/p&gt;  &lt;p&gt;HTML的版本表明HTML文件是按照哪个版本进行编写的（标明该HTML文件遵循的DTD文件），不同的版本和种类都有固定的书写格式，要按照固定的格式输入文件开头，然后在文件开头处写明版本，按照这种版本的规定格式进行编写&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;必须使用的标签&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;html&amp;gt;~&amp;lt;/html&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;head&amp;gt;~&amp;lt;/head&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;title&amp;gt;~&amp;lt;/title&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;body&amp;gt;~&amp;lt;/body&amp;gt;&lt;/p&gt;  &lt;p&gt;HTML文件的开头写有&amp;lt;!DOCTYPE~&amp;gt;的部分，代表HTML的版本，其后是必须存在的四种标签&lt;/p&gt;  &lt;p&gt;首先，&amp;lt;!DOCTYPE~&amp;gt;后面的整个都要用html标签(&amp;lt;html&amp;gt;~&amp;lt;/html&amp;gt;)括起来，其中要按照head标签(&amp;lt;head&amp;gt;~&amp;lt;/head)和body标签的顺序(&amp;lt;body&amp;gt;~&amp;lt;/body&amp;gt;)的顺序进行排列。&lt;/p&gt;  &lt;p&gt;在head标签中填写与该文件相关的信息，body标签中填写世纪要在浏览器上显示的内容。另外，在head标签中，只能有一个代表文件标题的title标签&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置页面的文字颜色&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;body text=”颜色指定”&amp;gt;~&amp;lt;/body&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置页面的背景颜色&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;body bgcolor=”颜色指定”&amp;gt;~&amp;lt;/body&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置页面的背景图像&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;body background=”图像的URL”&amp;gt;~&amp;lt;/body&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;按照目的设定范围&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;div&amp;gt;~&amp;lt;/div&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;span&amp;gt;~&amp;lt;/span&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;插入注释&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;!—注释语句--&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;strong&gt;、设置文件信息&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;添加标题&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;title&amp;gt;~&amp;lt;/title&amp;gt;&lt;/p&gt;  &lt;p&gt;title标签用来给HTML文件添加标题&lt;/p&gt;  &lt;p&gt;这个标签一定要位于&amp;lt;head&amp;gt;~&amp;lt;/head&amp;gt;圈定的范围内。在这里指定的标题除了可以在通常的浏览器窗口的标题栏中显示以外，还可以作为加入收藏夹时的标题&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;显示文件编码&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=文字编码&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;meta标签的charset属性表示该HTML文件是用什么文字编码编写的&lt;/p&gt;  &lt;p&gt;注意，该标签一定要位于&amp;lt;head&amp;gt;~&amp;lt;/head&amp;gt;范围内&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;添加关键字、内容介绍及作者姓名&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;meta name=&amp;quot;keywords&amp;quot; content=&amp;quot;关键字1，关键字2，…&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;meta name=&amp;quot;description&amp;quot; content=&amp;quot;内容介绍&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;meta name=&amp;quot;author&amp;quot; content=&amp;quot;作者姓名&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;这些信息都不会在画面上显示出来，但是搜索引擎在收集信息时要用到&lt;/p&gt;  &lt;p&gt;注意，该标签一定要位于&amp;lt;head&amp;gt;~&amp;lt;/head&amp;gt;范围内&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置样式表和脚本语言的种类&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;meta http-equiv=&amp;quot;Content-Style-Type&amp;quot; content=&amp;quot;样式表的种类&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;meta http-equiv=&amp;quot;Content-Script-Type&amp;quot; content=&amp;quot;脚本的种类&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;在HTML文件内可以设置样式表和脚本的默认语言&lt;/p&gt;  &lt;p&gt;注意，该标签一定要位于&amp;lt;head&amp;gt;~&amp;lt;/head&amp;gt;范围内&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置进入网页&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;link rel=”关系” href=”URL”&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;link rev=”关系” href=”URL”&amp;gt;&lt;/p&gt;  &lt;p&gt;rel：在本页看到的，与URL标明的网页之间的关系&lt;/p&gt;  &lt;p&gt;rev：在URL标明的网页中看到的，与本页之间的关系&lt;/p&gt;  &lt;p&gt;link标签表示的是该文件和与其相关的其他文件之间的关系&lt;/p&gt;  &lt;p&gt;注意，该标签一定要位于&amp;lt;head&amp;gt;~&amp;lt;/head&amp;gt;范围内&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置标准URL&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;base href=”绝对URL”&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;base href=”绝对URL” target=”目标名”&amp;gt;&lt;/p&gt;  &lt;p&gt;base标签用来设置将该页中使用的相对URL的标准指向成绝对URL，指定了这个标签之后，在该页指定的相对URL就会全部认定为已在这里指定的绝对URL。如果不进行这项设置，就以当前页的位置为标准，如果指定了Target属性，就可以指定打开链接地址网页的默认框架和窗口&lt;/p&gt;  &lt;p&gt;注意，该标签一定要位于&amp;lt;head&amp;gt;~&amp;lt;/head&amp;gt;范围内&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置自动倒入网页功能&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;秒数&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;meta http-equiv=&amp;quot;refresh&amp;quot; content=&amp;quot;秒数&amp;quot;；URL=要移动到的URL /&amp;gt;&lt;/p&gt;  &lt;p&gt;在经过数秒后，自动开始导入网页。如果指定了要移动到的URL，就会导入URL指定的网页。如果没有指定，就会再次导入相同的页&lt;/p&gt;  &lt;p&gt;注意，该标签一定要位于&amp;lt;head&amp;gt;~&amp;lt;/head&amp;gt;范围内&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;strong&gt;、设置文本类型&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置各级标题&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;h1&amp;gt;~&amp;lt;h1&amp;gt;&lt;/p&gt;  &lt;p&gt;…&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置段落&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;p&amp;gt;~&amp;lt;/p&amp;gt;&lt;/p&gt;  &lt;p&gt;p标签表示的是该部分为一个段落&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置联系地址&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;address&amp;gt;~&amp;lt;/address&amp;gt;&lt;/p&gt;  &lt;p&gt;address标签表示的内容是该网页制作者的联系地址和有关网页内容的咨询地址等信息&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置强调内容&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;em&amp;gt;~&amp;lt;/em&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;strong&amp;gt;~&amp;lt;/strong&amp;gt;&lt;/p&gt;  &lt;p&gt;这两个标签所圈内容表示该部分是强调的内容&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置较短的引用文字&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;q&amp;gt;~&amp;lt;/q&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;q cite=”引用页的URL”&amp;gt;~&amp;lt;/q&amp;gt;&lt;/p&gt;  &lt;p&gt;q标签代表的意思是该部分为较短的引用文，在引用段落的某一部分的时候使用，如果使用cite属性，还能够把引用页的URL显示出来&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置较长的引用文章&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;blockquote&amp;gt;~&amp;lt;/blockquote&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;blockquote cite=”引用页的URL”&amp;gt;~&amp;lt;/blockquote&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置文字内容的出处&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;cite&amp;gt;~&amp;lt;/cite&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置缩略语&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;abbr title=”字符串”&amp;gt;~&amp;lt;/abbr&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;acronym title=”字符串”&amp;gt;~&amp;lt;/acronym&amp;gt;&lt;/p&gt;  &lt;p&gt;title：不处于省略状态下的词汇（字符串）&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置添加的内容&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;ins cite=”URL” datetime=”添加日期时间”&amp;gt;~&amp;lt;/ins&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置需要删除的内容&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;de cite=”URL” datetime=”删除日期时间”&amp;gt;~&amp;lt;/del&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;突出显示段落中的术语&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;dfn&amp;gt;~&amp;lt;/dfn&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;表示与程序关联的文本&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;kbd&amp;gt;~&amp;lt;/kbd&amp;gt;：输入文本&lt;/p&gt;  &lt;p&gt;&amp;lt;samp&amp;gt;~&amp;lt;/samp&amp;gt;：输出样本&lt;/p&gt;  &lt;p&gt;&amp;lt;code&amp;gt;~&amp;lt;/code&amp;gt;：源代码&lt;/p&gt;  &lt;p&gt;&amp;lt;var&amp;gt;~&amp;lt;/var&amp;gt;：变量&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;显示特殊符号&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;amp;lt：&amp;lt;&lt;/p&gt;  &lt;p&gt;&amp;amp;gt：&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;amp;quot：”&lt;/p&gt;  &lt;p&gt;&amp;amp;amp：&amp;amp;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;strong&gt;、设置显示方式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置文字的换行&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;br&amp;gt;&lt;/p&gt;  &lt;p&gt;添加了br标签之后，文本就会再该处换行。即使在HTML代码中已经换行了，在浏览器上显示的时候却反映不出来，因此如果想在浏览器上换行的话，就要使用br标签&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;添加不同横线效果&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;hr&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;hr size=”粗细” width=”长度” align=”对齐方式” noshade&amp;gt;&lt;/p&gt;  &lt;p&gt;加入了hr标签后，就可以在其标注的地方显示横线&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置文本格式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;b&amp;gt;~&amp;lt;/b&amp;gt;：黑体字&lt;/p&gt;  &lt;p&gt;&amp;lt;i&amp;gt;~&amp;lt;/i&amp;gt;：斜体字&lt;/p&gt;  &lt;p&gt;&amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt;：等大字体&lt;/p&gt;  &lt;p&gt;&amp;lt;sup&amp;gt;~&amp;lt;/sup&amp;gt;：上标&lt;/p&gt;  &lt;p&gt;&amp;lt;sub&amp;gt;~&amp;lt;/sub&amp;gt;：下标&lt;/p&gt;  &lt;p&gt;&amp;lt;u&amp;gt;~&amp;lt;/u&amp;gt;：下划线&lt;/p&gt;  &lt;p&gt;&amp;lt;s&amp;gt;~&amp;lt;/s&amp;gt;：删除线&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置空格和换行&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;pre&amp;gt;~&amp;lt;/pre&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;pre&amp;gt;标签可以保留文字在源代码中的格式，使得页面中显示的内容和源代中的格式完全一致&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置居中效果&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;center&amp;gt;~&amp;lt;/center&amp;gt;&lt;/p&gt;  &lt;p&gt;center标签用于将指定范围内的内容设置为居中&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置行对齐方式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;h1 align=”行对齐方式”&amp;gt;~&amp;lt;h1&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;p align=”行对齐方式”&amp;gt;~&amp;lt;p&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;div align=”行对齐方式”&amp;gt;~&amp;lt;div&amp;gt;&lt;/p&gt;  &lt;p&gt;使用align属性可以设置标题、段落以及指定范围内的行对齐方式&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置文字颜色&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;font color=”设置颜色”&amp;gt;~&amp;lt;/font&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置字体类型&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;font&amp;gt;字体名”&amp;gt;~&amp;lt;/font&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置字体字号&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;font size=”字号”&amp;gt;~&amp;lt;/font&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;相对改变字体大小&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;big&lt;strong&gt;&amp;gt;~&amp;lt;/&lt;/strong&gt;big&lt;strong&gt;&amp;gt;&lt;/strong&gt;：增大&lt;/p&gt;  &lt;p&gt;&amp;lt;small&amp;gt;~&amp;lt;/small&amp;gt;：减小&lt;/p&gt;  &lt;p&gt;&amp;lt;font size=”+n”&amp;gt;：增大n号&lt;/p&gt;  &lt;p&gt;&amp;lt;font size=”-n”&amp;gt;：减小n号&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置字号的基本大小&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;basefont size=”字号”&amp;gt;&lt;/p&gt;  &lt;p&gt;size：1~7&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;6&lt;/strong&gt;&lt;strong&gt;、设置链接相关的属性&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;链接到其他页面&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;a href=”链接目标URL”&amp;gt;~&amp;lt;/a&amp;gt;&lt;/p&gt;  &lt;p&gt;a标签的href属性能把指定的范围链接到其他页面上，链接部分的词语要设置得让人看到这个部分就能联想到链接网页上的具体内容&lt;/p&gt;  &lt;p&gt;另外，在链接图像的时候，一定要插入替代的文字（alt=”~”）使用户能够很明确的了解到链接的目标&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;链接到当前页的特定位置&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;a href=”#位置名”&amp;gt;~&amp;lt;/a&amp;gt;：指定链接文件（从什么位置开始链接）&lt;/p&gt;  &lt;p&gt;&amp;lt;a name=”位置名”&amp;gt;~&amp;lt;/a&amp;gt;：指定链接的地址（要链接的位置）&lt;/p&gt;  &lt;p&gt;如果一页上的内容非常多，可以在一个网页中给特定的位置命名，然后再链接到该位置（跳转）。在给链接对象位置命名的时候要使用name属性。然后，在链接的时候，要用href属性在链接地址名称的前面加上#号&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置链接到其他页面的特定位置&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;a href=”URL#位置名”&amp;gt;~&amp;lt;/a&amp;gt;：指定链接源（从什么位置开始链接）&lt;/p&gt;  &lt;p&gt;&amp;lt;a name=”位置名”&amp;gt;~&amp;lt;/a&amp;gt;：指定链接的地址（要链接的位置）&lt;/p&gt;  &lt;p&gt;在链接到其他网页上的时候，可以先给那一页上特定的位置命名，然后链接到该位置。在给链接对象位置命名的时候要使用name属性。然后，在链接的时候，要用href属性设置成”URL+#+位置名”这样一种格式&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置链接文字的颜色&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;body link=”指定颜色” vlink=”指定颜色” alink=”指定颜色”&amp;gt;~&amp;lt;body&amp;gt;&lt;/p&gt;  &lt;p&gt;link：还没有看见的链接部分的文字颜色&lt;/p&gt;  &lt;p&gt;vlink：已经看见的链接部分的文字颜色&lt;/p&gt;  &lt;p&gt;alink：鼠标单击链接部分的文字颜色&lt;/p&gt;  &lt;p&gt;body标签用于设置网页整体链接部分的文字颜色&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;在新窗口中打开链接网页&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;a href=” URL” target=”窗口名”&amp;gt;~&amp;lt;/a&amp;gt;&lt;/p&gt;  &lt;p&gt;利用target属性可以设置打开链接窗口的方式&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;通过设置链接来启动邮箱&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;a href=”mailto：邮箱地址”&amp;gt;~&amp;lt;/a&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;7&lt;/strong&gt;&lt;strong&gt;、制作不同类型的列表&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;为列表添加不同类型的标记&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;列表项目1&amp;lt;/li&amp;gt;&amp;lt;&amp;gt;&amp;lt;li&amp;gt;列表项目2&amp;lt;/li&amp;gt;…&amp;lt;ul&amp;gt;&lt;/p&gt;  &lt;p&gt;ul标签的作用是将列表（条款形式）加上圆点或方括号的标记。列表的整体要在&amp;lt;ul&amp;gt;~&amp;lt;/ul&amp;gt;标签范围内，在这之间的各个项目要在&amp;lt;li&amp;gt;~&amp;lt;/li&amp;gt;标签之内&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;更改列表标记&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;ul type=”标记种类”&amp;gt;~&amp;lt;/ul&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;li type=”标记种类”&amp;gt;~&amp;lt;/li&amp;gt;&lt;/p&gt;  &lt;p&gt;标记的种类包括disc、cicle和square&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作带序号的列表&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;列表项目1&amp;lt;/li&amp;gt;&amp;lt;&amp;gt;&amp;lt;li&amp;gt;列表项目2&amp;lt;/li&amp;gt;…&amp;lt;ol&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;改变序号的样式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;ol type=”序号样式”&amp;gt;~&amp;lt;/ol&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;li type=”序号样式”&amp;gt;~&amp;lt;/li&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;改变序号的顺序&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;ol start=”开始序号”&amp;gt;~&amp;lt;/ol&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;li value=”开始序号”&amp;gt;~&amp;lt;/li&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作包含专用语和解释的列表&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;dl&amp;gt;&amp;lt;dt&amp;gt;专用语&amp;lt;dt&amp;gt;&amp;lt;dd&amp;gt;对其解释&amp;lt;/dd&amp;gt;…&amp;lt;dl&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;8&lt;/strong&gt;&lt;strong&gt;、设置表格&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;表格的基本形式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table border=”边框的粗度”&amp;gt;~&amp;lt;/table&amp;gt;：整个表格&lt;/p&gt;  &lt;p&gt;&amp;lt;tr&amp;gt;~&amp;lt;/tr&amp;gt;：单独一行&lt;/p&gt;  &lt;p&gt;&amp;lt;th&amp;gt;~&amp;lt;/th&amp;gt;：单元格：标题用&lt;/p&gt;  &lt;p&gt;&amp;lt;td&amp;gt;~&amp;lt;/td&amp;gt;：单元格：数据用&lt;/p&gt;  &lt;p&gt;表格的整体要圈在&amp;lt;table&amp;gt;~&amp;lt;/table&amp;gt;之间显示，表格当中某一个单元格用&amp;lt;th&amp;gt;~&amp;lt;/th&amp;gt;表示或者&amp;lt;td&amp;gt;~&amp;lt;/td&amp;gt;表示。每个单元格都在表的单独以行，放置在&amp;lt;tr&amp;gt;~&amp;lt;/tr&amp;gt;中。也就是说，table标签的内容是由tr标签构成的。各个tr标签的内容是由表示单元格的th或者td标签构成的。th标签代表这个单元格的内容是标题。td标签代表这个单元格的内容是数据&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;为表格添加标题&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;caption&amp;gt;~&amp;lt;/caption&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;caption align=”对齐方式”&amp;gt;~&amp;lt;/caption&amp;gt;&lt;/p&gt;  &lt;p&gt;caption标签用来给表格添加标题&lt;/p&gt;  &lt;p&gt;该标签一定要放在table标签的紧后面。标题的显示位置（即对齐方式）可以指定在表格的上部，或者表格的下部&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;指定表格的大小&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table width=”宽度”&amp;gt;~&amp;lt;/table&amp;gt;&lt;/p&gt;  &lt;p&gt;宽度：针对像素或者窗口的百分比&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;指定单元格大小&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;th width=”宽度” height=”高度”&amp;gt;~&amp;lt;/th&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;td width=”宽度” height=”高度”&amp;gt;~&amp;lt;/td&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;合并单元格&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;th rowspan=”垂直方向的合并数”&amp;gt;~&amp;lt;/th&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;th colspan=”水平方向的合并数”&amp;gt;~&amp;lt;/th&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;td rowspan=”垂直方向的合并数”&amp;gt;~&amp;lt;/td&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;td colspan=”水平方向的合并数”&amp;gt;~&amp;lt;/td&amp;gt;&lt;/p&gt;  &lt;p&gt;垂直方向的合并数：从当前单元格开始向下合并的单元格数&lt;/p&gt;  &lt;p&gt;水平方向的合并数：从当前单元格开始向右合并的单元格数&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置单元格之间的距离&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table cellspacing=”单元格的距离”&amp;gt;~&amp;lt;/table&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置单元格边框与内容之间的距离&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table cellpadding=”单元格边框与内容之间的距离”&amp;gt;~&amp;lt;/table&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置单元格中的行对齐方式和列对齐方式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;align属性用于设置单元格内的行对齐方式，valign属性用来设置单元格内的列对齐方式&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;禁止在单元格内换行&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;th nowrap&amp;gt;~&amp;lt;/th&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;td nowrap&amp;gt;~&amp;lt;/td&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置表格和单元格的背景颜色&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;bgcolor属性用于指定表格和单元格中的背景颜色&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置表格和单元格的背景图像&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;background属性用于指定表格和单元格中的背景图像&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置表格外框的宽度&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table border=”外框的宽度”&amp;gt;~&amp;lt;/table&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置表格外框的显示形式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table frame=”外框的显示形式”&amp;gt;~&amp;lt;/table&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置表格内补边框线的显示形式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table rules=”内部边框线的显示形式”&amp;gt;~&amp;lt;/table&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;定义表格中的横行&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;thead&amp;gt;~&amp;lt;/thead&amp;gt;：表头部分&lt;/p&gt;  &lt;p&gt;&amp;lt;tbody&amp;gt;~&amp;lt;/tbody&amp;gt;：表体部分&lt;/p&gt;  &lt;p&gt;&amp;lt;tfoot&amp;gt;~&amp;lt;/tfoot&amp;gt;：表底部分&lt;/p&gt;  &lt;p&gt;thead标签、tbody标签和tfoot标签都是用来定义表格的横行（tr标签）的&lt;/p&gt;  &lt;p&gt;这样组合之后，就可以针对该组合的整体来应用属性和样式表。&lt;/p&gt;  &lt;p&gt;使用这些标签的时候，一定要以thead标签、tfoot标签和tbody标签的顺序进行排列。在一个表格里，只能放置一个thead标签和一个tfoot标签，而tbody标签可以根据需要放置多个&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;利用纵列设置表格属性和样式表&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;col span=”纵列数”&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;col span=”纵列数” width=”宽度”&amp;gt;&lt;/p&gt;  &lt;p&gt;col标签不仅可以用来改变表格的纵列结构，还可以用来根据纵列，来综合指定宽和行对齐方式等属性以及样式表&lt;/p&gt;  &lt;p&gt;该标签放置的位置要在caption标签的紧后面（如果没有caption标签，就放在table标签的开始标签的紧后面），以及thead标签和tr标签的前面&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置表格居中&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table align=”center”&amp;gt;~&amp;lt;/table&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;将表格嵌入到文本中&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table align=”对齐方式”&amp;gt;~&amp;lt;/table&amp;gt;&lt;/p&gt;  &lt;p&gt;位置：left,right&lt;/p&gt;  &lt;p&gt;将table标签的align属性指定为left或者right后，就可以将表格以居左或居右的方式嵌入到文字中间&lt;/p&gt;  &lt;p&gt;如果想要解除嵌入状态，可以使用&amp;lt;br&amp;gt;标签的clear属性&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;解除表格的嵌套&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;br clear=”解除表格那一侧的嵌套”&amp;gt;&lt;/p&gt;  &lt;p&gt;left：解除左侧表格的嵌套&lt;/p&gt;  &lt;p&gt;right：解除右侧表格的嵌套&lt;/p&gt;  &lt;p&gt;all：解除两侧表格的嵌套&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置表格与嵌套文字之间的距离&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;table vspace=”垂直距离” hspace=”水平距离”&amp;gt;~&amp;lt;/table&amp;gt;&lt;/p&gt;  &lt;p&gt;垂直距离：表格的上下框与文字间的距离&lt;/p&gt;  &lt;p&gt;水平距离：表格的左右框与文字间的距离&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;9&lt;/strong&gt;&lt;strong&gt;、设置图像与多媒体&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;插入图像&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;img src=”URL” width=”宽度” hignt=”高度” alt=”替代文字”&amp;gt;&lt;/p&gt;  &lt;p&gt;使用img标签，可以把图像插入到HTML文件中&lt;/p&gt;  &lt;p&gt;图像的格式一般可以使用GIF格式、JPEG格式和PNG格式&lt;/p&gt;  &lt;p&gt;不管图像实际的大小如何，都会按照在这里所指定的宽度和高度来显示&lt;/p&gt;  &lt;p&gt;alt属性是在不能显示图像的情况下，指定替代图像所使用的文字&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置图像的边框&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;img src=”URL” alt=”替代文字” border=”边框的粗度”&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置图像与文字的垂直位置关系&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;img src=”URL” alt=”替代文字” align=”对齐方式”&amp;gt;&lt;/p&gt;  &lt;p&gt;在同一行中，如果有图像和文字，那么就可以用align属性来设置图像和文字的垂直位置关系&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作图像热区&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;img src=”URL” alt=”替代文字” usemap=”#map名”&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;map name=”map名”&amp;gt;~&amp;lt;/map&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;area shape=”形状” cords=”坐标” href=”URL” alt=”替代文字”&amp;gt;&lt;/p&gt;  &lt;p&gt;在map标签中，用来设置实际单击的区域和链接地址的是area标签&lt;/p&gt;  &lt;p&gt;在area标签中，一定要指定表示链接地址的替代文字，之后要用image标签的usemap属性指定定义后的image map的名称（名称前面要加#），这样图像就可以作为image map产生相应的效果&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;将图像嵌套在文本中&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;img src=”URL” alt=”替代文字” align=”对齐方式”&amp;gt;&lt;/p&gt;  &lt;p&gt;位置：left,right&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;解除图像的嵌套&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;br clear=”解除哪一侧图像的嵌套”&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置图像与周围文字之间的距离&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;img src=”URL” alt=”替代文字” vspace=”垂直距离” hspace=”水平距离”&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;放置Java&lt;/strong&gt;&lt;strong&gt;小程序&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;applet code=”类文件名” width=”宽度” height=”高度” &amp;gt;~&amp;lt;/applet&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;param name=”参数名” value=”参数值”&amp;gt;&lt;/p&gt;  &lt;p&gt;applet标签是嵌入Java小程序时要使用的标签&lt;/p&gt;  &lt;p&gt;如果使用param标签，在执行java小程序时，需事先指定一些必要值。这时，param标签要位于&amp;lt;applet&amp;gt;~&amp;lt;/applet&amp;gt;范围的最开始部分&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;strong&gt;、制作不同类型的表单&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作填写表单&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;form action=”URL” method=”发送形式” enctype=”MIME类型” target=”窗口名称”&amp;gt;~&amp;lt;/form&amp;gt;&lt;/p&gt;  &lt;p&gt;URL：用来处理发送后表格的程序的URL&lt;/p&gt;  &lt;p&gt;发送形式：get,post&lt;/p&gt;  &lt;p&gt;MIME类型：以post方式发送内容时的MIME类型&lt;/p&gt;  &lt;p&gt;窗口名称：先是发送结果的窗口或框架名&lt;/p&gt;  &lt;p&gt;form标签表示在表单中填写的内容是可以发送的&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作发送按钮&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”submit” value=”标签” name=”名称”&amp;gt;&lt;/p&gt;  &lt;p&gt;标签：在按钮上显示的文字&lt;/p&gt;  &lt;p&gt;名称：按钮的名称&lt;/p&gt;  &lt;p&gt;将input标签的type属性设置为submit，再根据form标签的设置，可以制作发送填写在表单中数据的按钮&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作重置按钮&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”reset” value=”标签”&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作通用按钮&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”button” name=”名称” value=”标签”&amp;gt;&lt;/p&gt;  &lt;p&gt;通用按钮通常与JavaScript等脚本语言组合使用&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;利用图像来制作发送按钮&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”image” src=”URL” name=”名称” alt=”替代文字” align=”对齐方式”&amp;gt;&lt;/p&gt;  &lt;p&gt;通常，发送按钮都使用input type=”submit”代码，不过图像也可以作为发送按钮，具有发送功能。这时，图像被单击的位置将和表单的内容一起被发送&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作不同功能的发送按钮&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;button type=”类型” name=”名称” value=”发送值”&amp;gt;~&amp;lt;/button&amp;gt;&lt;/p&gt;  &lt;p&gt;类型：submit,reset,button&lt;/p&gt;  &lt;p&gt;button标签是用来制作按钮专用的&lt;/p&gt;  &lt;p&gt;通过指定type属性值，就可以产生具有不同功能的按钮，包括发送按钮、重置按钮和通用按钮。另外，在&amp;lt;button&amp;gt;~&amp;lt;/button&amp;gt;中放置相应的内容，可以作为按钮的标签显示出来。在需要进行其他处理并设置多个发送按钮的情况下，根据name属性和value属性所显示的值，接受方就可以分辨出单击的是哪一个发送按钮&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作单行文本框&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”text” name=”名称” value=”默认文字” size=”宽度” maxlength=”字符的最大输入数量”&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作多行文本框&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;textarea name=”名称” rows=”行数” cols=”宽度”&amp;gt;~&amp;lt;/textarea&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作输入密码的文本框&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”password” name=”名称” value=”默认文字” size=”宽度” maxlength=”字符的最大输入数量”&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;插入隐藏域&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”hidden” name=”名称” value=”发送值” &amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作单选按钮&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”radio” name=”名称” value=”发送文字” &amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”radio” name=”名称” value=”发送文字” checked&amp;gt;&lt;/p&gt;  &lt;p&gt;将input标签的type属性设置为radio，可以用来制作单选按钮。单选按钮是多个选项当中只能选择其一的按钮。作为公共项目的选项而使用的单选按钮，要把它们都指定为同一名称。另外，发送数据的时候，为了识别所选的是哪一项，要用value属性来指定相应的值&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作复选框&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”checkbox” name=”名称” value=”发送文字” &amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=” checkbox” name=”名称” value=”发送文字” checked&amp;gt;&lt;/p&gt;  &lt;p&gt;将input标签的type属性设置为checkbox，可以用来制作复选框。复选框可以在多个选项当中进行多项选择。作为公共项目的选项而使用的复选框，要把它们都指定为同一名称。另外，发送数据的时候，为了识别所选的是哪一项，要用value属性来指定相应的值&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作菜单&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;select name=”名称”&amp;gt;~&amp;lt;/select&amp;gt;：菜单整体&lt;/p&gt;  &lt;p&gt;&amp;lt;option value=”发送值”&amp;gt;~&amp;lt;/option&amp;gt;：菜单项&lt;/p&gt;  &lt;p&gt;&amp;lt;option selected&amp;gt;~&amp;lt;/option&amp;gt;：菜单项&lt;/p&gt;  &lt;p&gt;select标签用来制作菜单&lt;/p&gt;  &lt;p&gt;菜单的整体要在&amp;lt;select&amp;gt;~&amp;lt;/select&amp;gt;范围之内显示，然后按需要的数量在其中放置表示选项的&amp;lt;option&amp;gt;~&amp;lt;/option&amp;gt;。&amp;lt;option&amp;gt;~&amp;lt;/option&amp;gt;范围之内要写上实际菜单要显示的选项的名称。另外，如果省略了value属性，在这里记录的文字本身就会作为所选值发送&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;组合菜单选项&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;optgroup lable=”组合名称”&amp;gt;~&amp;lt;/optgroup&amp;gt;：制作组合菜单&lt;/p&gt;  &lt;p&gt;&amp;lt;option lable=”次选项”&amp;gt;~&amp;lt;/option&amp;gt;：组合内的选项&lt;/p&gt;  &lt;p&gt;组合名称：第一级显示的组合标题&lt;/p&gt;  &lt;p&gt;次选项：对应组合名称下面的在第二级显示出来的选项&lt;/p&gt;  &lt;p&gt;制作的菜单选项可以利用&amp;lt;select&amp;gt;~&amp;lt;/select&amp;gt;标签组合起来&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;制作下拉列表&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;select size=”行数” name=”名称” multiple&amp;gt;~&amp;lt;/select&amp;gt;：下拉列表框&lt;/p&gt;  &lt;p&gt;&amp;lt;option value=”发送值”&amp;gt;~&amp;lt;/option&amp;gt;：菜单项&lt;/p&gt;  &lt;p&gt;&amp;lt;option selected&amp;gt;~&amp;lt;/option&amp;gt;：菜单项&lt;/p&gt;  &lt;p&gt;在用于制作菜单的select标签中指定了size属性后，就可以显示下拉列表框&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;添加选择文件的功能&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;input type=”file” name=”名称”accept=”MIME”类型&amp;gt;&lt;/p&gt;  &lt;p&gt;将input标签的type属性设置为file，可以自动做成能够选择发送表单数据的文件按钮和文本框&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;综合利用菜单选项&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;fieldset&amp;gt;~&amp;lt;/fieldset&amp;gt;：组合&lt;/p&gt;  &lt;p&gt;&amp;lt;legend align=”对齐方式”&amp;gt;~&amp;lt;/legend&amp;gt;：组合的标题&lt;/p&gt;  &lt;p&gt;field标签用来把填写在表单中需要包含的输入内容和选项组合起来&lt;/p&gt;  &lt;p&gt;在&amp;lt;fieldset&amp;gt;~&amp;lt;/fieldset&amp;gt;的最开始部分放置legend标签，并且给该组合加上标题&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;将标签文字与项目一体化&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;label for=”参照ID”&amp;gt;~&amp;lt;/lable&amp;gt;&lt;/p&gt;  &lt;p&gt;参照ID：添加了标签的对象的id属性值&lt;/p&gt;  &lt;p&gt;lable标签的作用是在输入项和选项及其标签文字之间建立起明确的关联，并使其一体化&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;11&lt;/strong&gt;&lt;strong&gt;、利用框架布局网页&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置框架整体结构&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;frameset rows=”高度”&amp;gt;~&amp;lt;/frameset&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;frameset cols=”宽度”&amp;gt;~&amp;lt;/frameset&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;frame src=”URL” name=”框架名称”&amp;gt;&lt;/p&gt;  &lt;p&gt;高度：在垂直方向上分布的多个框架的高度，按从上到下的顺序依次用逗号隔开来指定&lt;/p&gt;  &lt;p&gt;宽度：在水平方向上分布的多个框架的宽度，按从左到右的顺序依次用逗号隔开来指定&lt;/p&gt;  &lt;p&gt;URL：作为框架内容显示的HTML文件的URL&lt;/p&gt;  &lt;p&gt;框架名称：在指定链接等显示目标的时候使用的名称&lt;/p&gt;  &lt;p&gt;使用框架功能可以把窗口横竖切割开，然后在不同的块区域中显示其他的HTML文件。在指定了框架的文件中，原来body标签所在的位置，要放置frameset标签，这主要是由于在框架页面中不能使用body标签&lt;/p&gt;  &lt;p&gt;在&amp;lt;frameset&amp;gt;~&amp;lt;/frameset&amp;gt;的范围中要按照顺序填入分割后框架内要填写的内容。如果不需要再分割，就用frame标签指定要导入的HTML文件，如果还要继续分割的话，就需要放置frameset标签（作为嵌套放置在里面，并且指定盖框架如何分割）&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置框架的显示方法&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;frame scrolling=”滚动控制” noresize&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;frame marginwidth=”左右缩进” marginheight=”上下缩进”&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;设置是否显示边框&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;frame frameborder=”显示指定框架的边框”&amp;gt;&lt;/p&gt;  &lt;p&gt;frameborder属性用来设置分割开相邻框架的边框是否显示&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;去除分割框架的边框&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;frameset frameborder=”0” framespacing=”0” border=”0”&amp;gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;在不支持框架的环境中显示所需内容&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;noframes&amp;gt;~&amp;lt;/noframes&amp;gt;&lt;/p&gt;  &lt;p&gt;这个标签要在&amp;lt;frameset&amp;gt;~&amp;lt;/frameset&amp;gt;范围的最开始或者最后处放置一个。在&amp;lt;noframes&amp;gt;~&amp;lt;/noframes&amp;gt;范围内要首先放置body标签，并在其中填写所要显示的内容。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;指定链接目标在哪一个框架内显示&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;a href=”URL” target=”框架名”&amp;gt;~&amp;lt;/a&amp;gt;&lt;/p&gt;  &lt;p&gt;如果对框架内的文件中指定的链接不进行设置的话，就会在原来的相同框架中显示链接目标，如果想使这个链接目标在其他框架中显示的话，就需要指定target属性值，用想要显示（frame标签）的那个框架的name属性来指定框架名称&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;插入内嵌框架&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;iframe src=”内容的URL” name=”框架名”&amp;gt;~&amp;lt;/iframe&amp;gt;&lt;/p&gt;  &lt;p&gt;iframe标签不仅可以放置分割窗口形式的框架，还可以在窗口中放置独立显示的内嵌框架。在框架内还可以显示src属性所指定的内容&lt;/p&gt;  &lt;p&gt;如果浏览器不支持这种框架，要在&amp;lt;iframe&amp;gt;~&amp;lt;/iframe&amp;gt;之间指定要显示的内容&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;12&lt;/strong&gt;&lt;strong&gt;、关于脚本&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;在HTML&lt;/strong&gt;&lt;strong&gt;中插入脚本&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;script type=”MME类型”&amp;gt;~&amp;lt;/script&amp;gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;script type=”MME类型” language=”语言名称” src=”URL”&amp;gt;~&amp;lt;/script&amp;gt;&lt;/p&gt;  &lt;p&gt;在HTML文件中编写脚本的时候要用到script标签，脚本语言要写在这个标签的范围内&lt;/p&gt;  &lt;p&gt;这时，在不支持这个标签的浏览器上会在画面上显示出脚本的部分，为了避免这种现象，通常把脚本整体作为HTML的注释。这个标签可以放在&amp;lt;head&amp;gt;~&amp;lt;/head&amp;gt;和&amp;lt;body&amp;gt;~&amp;lt;/body&amp;gt;范围内的任意位置上&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;在不能执行脚本的环境中添加所需的内容&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;lt;noscript&amp;gt;~&amp;lt;/noscript&amp;gt;&lt;/p&gt;  &lt;p&gt;在脚本不能运行的时候，可以使用noscript标签来指定替代显示的内容&lt;/p&gt;  &lt;p&gt;这个标签要放置在&amp;lt;body&amp;gt;~&amp;lt;/body&amp;gt;的范围内&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.cnblogs.com/ustcwhc/archive/2011/11/09/2243056.html" href="http://www.cnblogs.com/ustcwhc/archive/2011/11/09/2243056.html"&gt;http://www.cnblogs.com/ustcwhc/archive/2011/11/09/2243056.html&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2253489.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2011/11/18/2253489.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/HeroBeast/archive/2011/10/18/2216196.html</id><title type="text">dhcp分配不到IP地址的解决方法</title><summary type="text">netsh winsock reset</summary><published>2011-10-18T02:50:00Z</published><updated>2011-10-18T02:50:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2011/10/18/2216196.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2011/10/18/2216196.html"/><content type="html">&lt;p&gt;netsh winsock reset&lt;/p&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2216196.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2011/10/18/2216196.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178269.html</id><title type="text">使用CruiseControl+SVN+ANT实现持续集成之三</title><summary type="text">在上一节中我们介绍了环境搭建和配置介绍，并快速启动CC查看集成结果，在本节中我们将详细介绍CC构建操作及监视。 1. 启动CC服务器 通过执行其根目录下的cruisecontrol.bat文件来启动CC。控制台显示“BuildQueue - BuildQueue started”，则说明CC服务器已成功启动。 在启动服务器之前，我们可以打开cruisecontrol.bat文...</summary><published>2011-09-16T01:18:00Z</published><updated>2011-09-16T01:18:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178269.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178269.html"/><content type="html">&lt;p&gt;在上一节中我们介绍了环境搭建和配置介绍，并快速启动CC查看集成结果，在本节中我们将详细介绍CC构建操作及监视。    &lt;br /&gt;&lt;strong&gt;1. 启动CC服务器&lt;/strong&gt;&lt;strong&gt;      &lt;br /&gt;&lt;/strong&gt;通过执行其根目录下的cruisecontrol.bat文件来启动CC。控制台显示“BuildQueue - BuildQueue started”，则说明CC服务器已成功启动。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image002.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;在启动服务器之前，我们可以打开cruisecontrol.bat文件并修改倒数第三行相应功能的端口数值来指定服务器占用的系统端口，在本例中我们将默认8080端口。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image004.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2. Report管理方式&lt;/strong&gt;&lt;strong&gt;      &lt;br /&gt;&lt;/strong&gt;在前一节中介绍CC有两个入口可以管理集成项目，其中CC较早之前提供了Report方式控制主界面，通过&lt;a href="http://localhost:8080/cruisecontrol/"&gt;http://localhost:8080/cruisecontrol/&lt;/a&gt; 进入，界面如下：&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image006.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;在列表中显示了各个项目的相关信息，包括当前状态、上次失败时间、上次成功时间、构建次数等信息，同时Build按钮可以让CC立即检测工程状态。 点击相应工程名称，则可以进入该工程的详细页面首页，首页清晰明了，主要包括了构建历史信息、最近构建结果、最近构建版本信息等，该页面可以让我们对当前工程的集成信息一目了然，便于我们对不同的集成结果做出相应的处理。页面上部的导航按钮可以让我们进入不同信息的查看界面，包括构建结果、测试结果、XML详细日志文件、状态统计、应用配置、控制台配置等信息。这些导航按钮根据工程设置的不同扩展任务而有所不同。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image008.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.1. 构建结果      &lt;br /&gt;&lt;/strong&gt;在第一个tag页上最上方显示的是该项目最新构建的基本信息（包括构建日期、时间、项目文件最近修改时间）、编译中的警告和错误、自动化测试结果以及本次项目变化具体的明细。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image010.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.2. 测试结果      &lt;br /&gt;&lt;/strong&gt;该tag页显示了自动化测试结果，该结果按照测试类分类，在每个测试类下显示了每一个方法的测试结果以及用时。每一个测试类中都有控制台输出日志，点击进入”system.out” 可以查看具体日志信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image012.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.3. XML详细日志文件      &lt;br /&gt;&lt;/strong&gt;记录该项目所有构建信息，如下图所示。     &lt;br /&gt;在该文件中记录了项目的基本信息、最后构建时间、最后成功构建时间、构建时间等信息，另外也包括项目配置信息，如JDK版本、构建操作系统等。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image014.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.4. 状态统计      &lt;br /&gt;&lt;/strong&gt;该tag页面通过不同类型图形显示了项目构建状态信息，在tag页面上方显示了页面总构建次数、成功次数和失败次数，接下来通过饼图显示成功与失败次数对比等统计信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image016.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image018.jpg" /&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image020.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.5. 应用配置      &lt;br /&gt;&lt;/strong&gt;CC支持在页面是配置Config.xml文件，首先可以通过“Reload from server”加载该应用的配置信息，配置内容包括Listeners、bootstrappers、Source Controls、Schedule、Log、Publishers等节点，修改完毕后点击“OK”按钮保存配置信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image022.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.6. 控制台配置      &lt;br /&gt;&lt;/strong&gt;在该tag页中可以对该项目控制进行配置，具体包括构建轮询时间、版本标签号、发布包命名格式等信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image024.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3. Dashboard管理方式&lt;/strong&gt;&lt;strong&gt;      &lt;br /&gt;&lt;/strong&gt;我们现在比较常用的(也是CC推荐)是通过Dashboard界面来管理项目集成，其地址为 &lt;a href="http://localhost:8080/dashboard"&gt;http://localhost:8080/dashboard&lt;/a&gt;。该方式以不同颜色的色块表示不同项目构建的状态，能够直观地观察到不同项目当前状态，当把鼠标放在小方块上时，会显示该项目的主要信息。在页面的右边显示了构建项目的状态统计，能够了解构建概况。另外几个小工具，提供了RSS连接以及更加人性化页面配置工具。     &lt;br /&gt;在介绍Dashboard之前我们熟悉CC中项目的状态， CC把项目分成三类，Discontinued(停止)，Inactive(不活动)，及Active(活动)。&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Discontinued(停止)&lt;/strong&gt;表示CC可以找到该项目的日志文件，但在配置文件(Config.xml)中并没有该文件。所以CC不会去构建它，但你可以看到这个项目过去构建的历史信息。如果想把这个项目从CC中删除，只有把该项目的日志目录删除才行。如果该项目名为&amp;quot;petclinic&amp;quot;，目录当该是${CruiseContor.Home}/logs/petclinic。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Inactive(不活动)&lt;/strong&gt;表示CC在配置文件(Config.xml)中发现了该项目，但是没有发现关于这个项目的任何历史信息，即在CC的日志目录中还没有该项目的日志文件，或日志文件被人为删除了。CC会根据配置信息对这个项目进行检查新版本并进行构建，当第一次构建完成后，CC就会生成日志，这个项目状态就会转为Active了 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Active(活动)&lt;/strong&gt;表示CC即可以找到该项目的日志文件，又在配置文件（Config.xml）中可以发现它。此时，这个项目可能是构建成功，也可能是构建失败，还可能是构建中。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Dashboard主要有四个tag页面，它们分别是Dashboard，Builds，Build Details和Administatiorn。    &lt;br /&gt;&lt;strong&gt;3.1. Dashboard      &lt;br /&gt;&lt;/strong&gt;在Dashboard tab页面左边可看到所有项目的状态，不同颜色色块表示不同的构建状态&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;红色方块表示该项目最近一次构建是失败的 &lt;/li&gt;    &lt;li&gt;绿色方块表示该项目最近一次构建是成功的 &lt;/li&gt;    &lt;li&gt;灰色方块表示该项目可能是Inactive的，也可能是Discontinued。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;另外在页面的右边看以看到对所有构建项目的统计信息，不同图标、数目表示所处不同状态项目的个数。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image026.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3.2. Builds      &lt;br /&gt;&lt;/strong&gt;在该tab页面左中部显示了所有构建项目状态统计信息，右中部则是不同工具的链接，页面底部以列表方式展示了所有项目构建信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image028.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;在每一笔构建信息中点击 &lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image030.jpg" /&gt;可以看到所有构建，点击 &lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image032.jpg" /&gt;图标可以查看所有成功构建。如果你将Force Build配置为true，在列表右侧有一个按钮 &lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image034.jpg" /&gt;，点击该图标可以强迫该项目进行构建，而不必等到其下一次检查，也不必等到它有版本变化。点击后在Builds页面和Dashboard页面可以看到正在构建图标。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image036.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image038.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;另外可以通过有工具图标进行该项目RSS和JMX控制台配置，其操作见Report管理方式1.2.6部分&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image040.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3.3. Build Details      &lt;br /&gt;&lt;/strong&gt;此tab页面会列出该项目某次构建的详细信息，包括项目文件最近修改记录、构建日志、自动化测试结果、构建警告和错误，如果构建成功的话，在配置文件(config.xml)中配置的Artifacts也会在名为Artifacts的tab页上看到。     &lt;br /&gt;右侧的列表是该项目所有历史构建列表，点击其中一个构建，你就可以得到该次构建的详细信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image042.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3.4. Administration      &lt;br /&gt;&lt;/strong&gt;该页面你可以看到About和Configuration两个子标签。     &lt;br /&gt;在About子标签中，你可以看到CC所用的环境信息，如CC的版本号、所用的操作系统和JDK版本等。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image044.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;在Administration子标签中，你可以看到CC的Dashboard-config.xml文件内容。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image046.jpg" /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2178269.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178269.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178254.html</id><title type="text">使用CruiseControl+SVN+ANT实现持续集成之三</title><summary type="text">在上一节中我们介绍了环境搭建和配置介绍，并快速启动CC查看集成结果，在本节中我们将详细介绍CC构建操作及监视。 1. 启动CC服务器 通过执行其根目录下的cruisecontrol.bat文件来启动CC。控制台显示“BuildQueue - BuildQueue started”，则说明CC服务器已成功启动。 在启动服务器之前，我们可以打开cruisecontrol.bat文件并...</summary><published>2011-09-16T01:01:00Z</published><updated>2011-09-16T01:01:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178254.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178254.html"/><content type="html">&lt;p&gt;在上一节中我们介绍了环境搭建和配置介绍，并快速启动CC查看集成结果，在本节中我们将详细介绍CC构建操作及监视。   &lt;br /&gt;&lt;strong&gt;1. 启动CC服务器&lt;/strong&gt;&lt;strong&gt;     &lt;br /&gt;&lt;/strong&gt;通过执行其根目录下的cruisecontrol.bat文件来启动CC。控制台显示“BuildQueue - BuildQueue started”，则说明CC服务器已成功启动。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image002.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;在启动服务器之前，我们可以打开cruisecontrol.bat文件并修改倒数第三行相应功能的端口数值来指定服务器占用的系统端口，在本例中我们将默认8080端口。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image004.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2. Report管理方式&lt;/strong&gt;&lt;strong&gt;     &lt;br /&gt;&lt;/strong&gt;在前一节中介绍CC有两个入口可以管理集成项目，其中CC较早之前提供了Report方式控制主界面，通过&lt;a href="http://localhost:8080/cruisecontrol/"&gt;http://localhost:8080/cruisecontrol/&lt;/a&gt; 进入，界面如下：&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image006.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;在列表中显示了各个项目的相关信息，包括当前状态、上次失败时间、上次成功时间、构建次数等信息，同时Build按钮可以让CC立即检测工程状态。 点击相应工程名称，则可以进入该工程的详细页面首页，首页清晰明了，主要包括了构建历史信息、最近构建结果、最近构建版本信息等，该页面可以让我们对当前工程的集成信息一目了然，便于我们对不同的集成结果做出相应的处理。页面上部的导航按钮可以让我们进入不同信息的查看界面，包括构建结果、测试结果、XML详细日志文件、状态统计、应用配置、控制台配置等信息。这些导航按钮根据工程设置的不同扩展任务而有所不同。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image008.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.1. 构建结果     &lt;br /&gt;&lt;/strong&gt;在第一个tag页上最上方显示的是该项目最新构建的基本信息（包括构建日期、时间、项目文件最近修改时间）、编译中的警告和错误、自动化测试结果以及本次项目变化具体的明细。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image010.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.2. 测试结果     &lt;br /&gt;&lt;/strong&gt;该tag页显示了自动化测试结果，该结果按照测试类分类，在每个测试类下显示了每一个方法的测试结果以及用时。每一个测试类中都有控制台输出日志，点击进入”system.out” 可以查看具体日志信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image012.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.3. XML详细日志文件     &lt;br /&gt;&lt;/strong&gt;记录该项目所有构建信息，如下图所示。    &lt;br /&gt;在该文件中记录了项目的基本信息、最后构建时间、最后成功构建时间、构建时间等信息，另外也包括项目配置信息，如JDK版本、构建操作系统等。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image014.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.4. 状态统计     &lt;br /&gt;&lt;/strong&gt;该tag页面通过不同类型图形显示了项目构建状态信息，在tag页面上方显示了页面总构建次数、成功次数和失败次数，接下来通过饼图显示成功与失败次数对比等统计信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image016.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image018.jpg" /&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image020.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.5. 应用配置     &lt;br /&gt;&lt;/strong&gt;CC支持在页面是配置Config.xml文件，首先可以通过“Reload from server”加载该应用的配置信息，配置内容包括Listeners、bootstrappers、Source Controls、Schedule、Log、Publishers等节点，修改完毕后点击“OK”按钮保存配置信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image022.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2.6. 控制台配置     &lt;br /&gt;&lt;/strong&gt;在该tag页中可以对该项目控制进行配置，具体包括构建轮询时间、版本标签号、发布包命名格式等信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image024.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3. Dashboard管理方式&lt;/strong&gt;&lt;strong&gt;     &lt;br /&gt;&lt;/strong&gt;我们现在比较常用的(也是CC推荐)是通过Dashboard界面来管理项目集成，其地址为 &lt;a href="http://localhost:8080/dashboard"&gt;http://localhost:8080/dashboard&lt;/a&gt;。该方式以不同颜色的色块表示不同项目构建的状态，能够直观地观察到不同项目当前状态，当把鼠标放在小方块上时，会显示该项目的主要信息。在页面的右边显示了构建项目的状态统计，能够了解构建概况。另外几个小工具，提供了RSS连接以及更加人性化页面配置工具。    &lt;br /&gt;在介绍Dashboard之前我们熟悉CC中项目的状态， CC把项目分成三类，Discontinued(停止)，Inactive(不活动)，及Active(活动)。&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Discontinued(停止)&lt;/strong&gt;表示CC可以找到该项目的日志文件，但在配置文件(Config.xml)中并没有该文件。所以CC不会去构建它，但你可以看到这个项目过去构建的历史信息。如果想把这个项目从CC中删除，只有把该项目的日志目录删除才行。如果该项目名为&amp;quot;petclinic&amp;quot;，目录当该是${CruiseContor.Home}/logs/petclinic。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Inactive(不活动)&lt;/strong&gt;表示CC在配置文件(Config.xml)中发现了该项目，但是没有发现关于这个项目的任何历史信息，即在CC的日志目录中还没有该项目的日志文件，或日志文件被人为删除了。CC会根据配置信息对这个项目进行检查新版本并进行构建，当第一次构建完成后，CC就会生成日志，这个项目状态就会转为Active了 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Active(活动)&lt;/strong&gt;表示CC即可以找到该项目的日志文件，又在配置文件（Config.xml）中可以发现它。此时，这个项目可能是构建成功，也可能是构建失败，还可能是构建中。&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Dashboard主要有四个tag页面，它们分别是Dashboard，Builds，Build Details和Administatiorn。   &lt;br /&gt;&lt;strong&gt;3.1. Dashboard     &lt;br /&gt;&lt;/strong&gt;在Dashboard tab页面左边可看到所有项目的状态，不同颜色色块表示不同的构建状态&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;红色方块表示该项目最近一次构建是失败的 &lt;/li&gt;    &lt;li&gt;绿色方块表示该项目最近一次构建是成功的 &lt;/li&gt;    &lt;li&gt;灰色方块表示该项目可能是Inactive的，也可能是Discontinued。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;另外在页面的右边看以看到对所有构建项目的统计信息，不同图标、数目表示所处不同状态项目的个数。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image026.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3.2. Builds     &lt;br /&gt;&lt;/strong&gt;在该tab页面左中部显示了所有构建项目状态统计信息，右中部则是不同工具的链接，页面底部以列表方式展示了所有项目构建信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image028.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;在每一笔构建信息中点击 &lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image030.jpg" /&gt;可以看到所有构建，点击 &lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image032.jpg" /&gt;图标可以查看所有成功构建。如果你将Force Build配置为true，在列表右侧有一个按钮 &lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image034.jpg" /&gt;，点击该图标可以强迫该项目进行构建，而不必等到其下一次检查，也不必等到它有版本变化。点击后在Builds页面和Dashboard页面可以看到正在构建图标。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image036.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image038.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;另外可以通过有工具图标进行该项目RSS和JMX控制台配置，其操作见Report管理方式1.2.6部分&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image040.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3.3. Build Details     &lt;br /&gt;&lt;/strong&gt;此tab页面会列出该项目某次构建的详细信息，包括项目文件最近修改记录、构建日志、自动化测试结果、构建警告和错误，如果构建成功的话，在配置文件(config.xml)中配置的Artifacts也会在名为Artifacts的tab页上看到。    &lt;br /&gt;右侧的列表是该项目所有历史构建列表，点击其中一个构建，你就可以得到该次构建的详细信息。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image042.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3.4. Administration     &lt;br /&gt;&lt;/strong&gt;该页面你可以看到About和Configuration两个子标签。    &lt;br /&gt;在About子标签中，你可以看到CC所用的环境信息，如CC的版本号、所用的操作系统和JDK版本等。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image044.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;在Administration子标签中，你可以看到CC的Dashboard-config.xml文件内容。&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_3/image046.jpg" /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2178254.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178254.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178250.html</id><title type="text">使用CruiseControl+SVN+ANT实现持续集成之二</title><summary type="text">1. 环境搭建 1.1. 下载及目录介绍 从官方站点http://cruisecontrol.sourceforge.net/download.html下载一份最新的 CC 压缩包，最新的版本号为2.8.4 下载了cruisecontrol-bin-2.8.4.zip 直接解压到E盘下，文件结构如下图： apache-ant-1.7.0：CC中使用ANT工具 ...</summary><published>2011-09-16T00:55:00Z</published><updated>2011-09-16T00:55:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178250.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178250.html"/><content type="html">&lt;p&gt;&lt;strong&gt;1. 环境搭建&lt;/strong&gt;&lt;strong&gt;     &lt;br /&gt;1.1. 下载及目录介绍&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;从官方站点&lt;a href="http://cruisecontrol.sourceforge.net/download.html"&gt;http://cruisecontrol.sourceforge.net/download.html&lt;/a&gt;下载一份最新的 CC 压缩包，最新的版本号为2.8.4&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_2/image002.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;下载了cruisecontrol-bin-2.8.4.zip 直接解压到E盘下，文件结构如下图： &lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_2/image004.jpg" /&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;apache-ant-1.7.0：CC中使用ANT工具 &lt;/li&gt;    &lt;li&gt;artifacts：CC编译生成发布包 &lt;/li&gt;    &lt;li&gt;etc：自带容器Jetty对应的配置文件 &lt;/li&gt;    &lt;li&gt;lib：自带容器Jetty所需要到的Jar包 &lt;/li&gt;    &lt;li&gt;logs：各项目生成日志存在文件夹 &lt;/li&gt;    &lt;li&gt;projects：存放各项目文件目录，进行程序的编译 &lt;/li&gt;    &lt;li&gt;webapps：CC自带应用程序存放目录 &lt;/li&gt;    &lt;li&gt;cc-config：用于CC环境变量配置 &lt;/li&gt;    &lt;li&gt;cruisecontrol：主应用程序CC目录 &lt;/li&gt;    &lt;li&gt;dashboard：用于编译结果发布程序 &lt;/li&gt;    &lt;li&gt;documentation：CC相关文档 &lt;/li&gt;    &lt;li&gt;config.xml：用于CC编译配置文件，通过修改配置文件引入不同的插件，执行不同的编译流程 &lt;/li&gt;    &lt;li&gt;cruisecontrol.bat：在WINDOWS环境下进行启用CC批处理脚本 &lt;/li&gt;    &lt;li&gt;cruisecontrol.sh：在Linux等环境下启动CC脚本 &lt;/li&gt;    &lt;li&gt;dashboard-config.xml：Dashboard配置文件 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;1.2. 运行环境     &lt;br /&gt;&lt;/strong&gt;使用JAVA开发的CC，当然需要运行在JDK下并通过Web容器进行发布，具体要求如下：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;CC需要运行在至少JDK 1.4环境中，在环境变量中设置有JAVA_HOME，并把java/bin加入到path中； &lt;/li&gt;    &lt;li&gt;CC已经内建集成了ANT，不需要单独引入； &lt;/li&gt;    &lt;li&gt;CC可以运行在多种应用服务器中，在自带压缩包中捆绑了一个开源应用服务器，那就是Jetty 6，下面为了尽快建立我们的环境，以下将使用该容器。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;1.3. 快速启动CC     &lt;br /&gt;&lt;/strong&gt;运行根目录下批处理文件cruisecontrol.bat，出现如下界面：&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_2/image006.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;运行成功后，我们可以在浏览器输入 &lt;a href="http://localhost:8080/cruisecontrol/"&gt;http://localhost:8080/cruisecontrol/&lt;/a&gt; 来验证一下结果（采用Jetty默认的设置，端口号为 8080）&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_2/image008.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;如果看到上图结果，恭喜你已经成功启动CC。   &lt;br /&gt;另外CC提供了更加人性化结果展示Dashboard界面，在浏览器输入 &lt;a href="http://localhost:8080/dashboard/"&gt;http://localhost:8080/dashboard/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_2/image010.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2. 配置介绍&lt;/strong&gt;    &lt;br /&gt;当CC服务器启动时，会自动检测配置信息中的任务信息，并对其进行校验和初始化，之后所有的工作，都是依据该配置信息进行的。    &lt;br /&gt;CC的配置使用了其安装目录下的config.xml文件，我们可以通过文本编辑器打开该配置文件，编辑各种配置信息。配置信息的定义遵循了标准XML文件格式，同时遵循了ANT自动构建配置信息的规则。&lt;/p&gt;  &lt;p&gt;config.xml   &lt;br /&gt;&lt;strong&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;cruisecontrol&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;project&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;connectfour&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!-- 用来访问项目当前创建的状态&amp;#160;&amp;#160; file: 指定了状态文件的位置 --&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;listeners&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;currentbuildstatuslistener&lt;/span&gt; &lt;span style="color: #ff0000"&gt;file&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;logs/${project.name}/status.txt&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;listeners&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!-- 在 CC 进行创建之前运行，创建前的准备工作 --&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;bootstrappers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!-- 从源码控制系统更新本地文件: cvsbootstrappers、vssbootstrappers、svnbootstrapper --&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;antbootstrapper&lt;/span&gt; &lt;span style="color: #ff0000"&gt;anthome&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;apache-ant-1.7.0&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;buildfile&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;projects/${project.name}/build.xml&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;target&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;clean&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;bootstrappers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!-- 检查各个源码控制系统中是否发生变化；quietperiod: 单位为秒 设定等待的时间 --&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!-- 第一次的取出工作为手动执行 --&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;modificationset&lt;/span&gt; &lt;span style="color: #ff0000"&gt;quietperiod&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;30&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!-- touch any file in connectfour project to trigger a build --&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;filesystem&lt;/span&gt; &lt;span style="color: #ff0000"&gt;folder&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;projects/${project.name}&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;modificationset&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!-- 指定了构建的时间间隔 单位为秒--&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;schedule&lt;/span&gt; &lt;span style="color: #ff0000"&gt;interval&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;300&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ant&lt;/span&gt; &lt;span style="color: #ff0000"&gt;anthome&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;apache-ant-1.7.0&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;buildfile&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;projects/${project.name}/build.xml&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;schedule&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!-- 指定项目日志保存的地点 --&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;log&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;merge&lt;/span&gt; &lt;span style="color: #ff0000"&gt;dir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;projects/${project.name}/target/test-results&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;log&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!-- 在 build loop 结束之后运行,发布 build 的结果 --&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;publishers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;onsuccess&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!--用于对创建过程中产生的人工制品进行发布--&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;artifactspublisher&lt;/span&gt; &lt;span style="color: #ff0000"&gt;dest&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;artifacts/${project.name}&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;file&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;projects/${project.name}/target/${project.name}.jar&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;onsuccess&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000"&gt;&amp;lt;!--       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; mailhost=邮件主机        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; returnname=发件人        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; returnaddress=发件地址        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; defaultsuffix=默认邮件后缀        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; --&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;htmlemail&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;charset&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;mailhost&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;test163.com&amp;quot;&lt;/span&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;defaultsuffix&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;@xxx.com&amp;quot;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;username&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;xxx@163.com&amp;quot;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;password&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;xxx&amp;quot;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;returnname&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;CruiseControl&amp;quot;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;returnaddress&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;xxx@163.com&amp;quot;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;subjectprefix&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;构建日志&amp;quot;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;xsldir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;webapps/cruisecontrol/xsl&amp;quot;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #ff0000"&gt;css&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;webapps/cruisecontrol/css/cruisecontrol.css&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;always&lt;/span&gt; &lt;span style="color: #ff0000"&gt;address&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;xxx@xxx.com.cn&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;failure&lt;/span&gt; &lt;span style="color: #ff0000"&gt;address&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;xxx@xxx,yyy@yyy.com.cn&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;htmlemail&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;publishers&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;project&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;cruisecontrol&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;      &lt;br /&gt;build.xml&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;     &lt;pre&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;!-调用ANT执行集成流程，包括清空目录、编译、休眠、测试、打包 --&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
 &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;project&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;connectfour&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;default&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;all&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;all&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;depends&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;clean, compile, sleep, test, jar&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
 &#xD;
     &lt;span style="color: #008000"&gt;&amp;lt;!-- 1. 删除根目录下target 目录--&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;clean&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;delete&lt;/span&gt; &lt;span style="color: #ff0000"&gt;dir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;quiet&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
 &#xD;
     &lt;span style="color: #008000"&gt;&amp;lt;!-- 2. 编译程序，创建目录并编译程序，编译输出为target/classes目录下--&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;compile&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;mkdir&lt;/span&gt; &lt;span style="color: #ff0000"&gt;dir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/classes&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;javac&lt;/span&gt; &lt;span style="color: #ff0000"&gt;srcdir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;src&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;destdir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/classes&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
 &#xD;
     &lt;span style="color: #008000"&gt;&amp;lt;!-- 3. 在创建前等待60秒，用于Dashboard观察进程--&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;sleep&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;echo&lt;/span&gt; &lt;span style="color: #ff0000"&gt;message&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;Sleeping for a while so you can see the build in the new dashboard&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;sleep&lt;/span&gt; &lt;span style="color: #ff0000"&gt;seconds&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;60&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
 &#xD;
     &lt;span style="color: #008000"&gt;&amp;lt;!-- 4. 进行自动化测试，依赖任务为compile--&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;test&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;depends&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;compile&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;mkdir&lt;/span&gt; &lt;span style="color: #ff0000"&gt;dir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/test-classes&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;!-调用junit进行自动化测试--&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;javac&lt;/span&gt; &lt;span style="color: #ff0000"&gt;srcdir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;test&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;destdir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/test-classes&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;classpath&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
                 &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;pathelement&lt;/span&gt; &lt;span style="color: #ff0000"&gt;location&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/classes&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
                 &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;pathelement&lt;/span&gt; &lt;span style="color: #ff0000"&gt;location&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;lib/junit.jar&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
             &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;classpath&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;javac&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
 &#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;!-创建测试结果存放目录--&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;mkdir&lt;/span&gt; &lt;span style="color: #ff0000"&gt;dir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/test-results&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;junit&lt;/span&gt; &lt;span style="color: #ff0000"&gt;haltonfailure&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;no&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;printsummary&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;on&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;classpath&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
                 &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;pathelement&lt;/span&gt; &lt;span style="color: #ff0000"&gt;location&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/classes&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
                 &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;pathelement&lt;/span&gt; &lt;span style="color: #ff0000"&gt;location&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;lib/junit.jar&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
                 &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;pathelement&lt;/span&gt; &lt;span style="color: #ff0000"&gt;location&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/test-classes&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
             &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;classpath&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;formatter&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;brief&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;usefile&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;formatter&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;xml&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
 &#xD;
             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;!-测试文件所在文件地址--&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
             &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;batchtest&lt;/span&gt; &lt;span style="color: #ff0000"&gt;todir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/test-results&amp;quot;&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
                 &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;fileset&lt;/span&gt; &lt;span style="color: #ff0000"&gt;dir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/test-classes&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;includes&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;**/*Test.class&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
             &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;batchtest&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;junit&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
 &#xD;
     &lt;span style="color: #008000"&gt;&amp;lt;!-- 5. 程序打包，依赖与compile任务--&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;jar&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;depends&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;compile&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;jar&lt;/span&gt; &lt;span style="color: #ff0000"&gt;jarfile&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/connectfour.jar&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;basedir&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;target/classes&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&#xD;
     &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;target&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&#xD;
 &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;project&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
2.3. 执行配置解析&#xD;
&#xD;
    &lt;br /&gt;&lt;/strong&gt;一个持续集成项目是从project节点开始的，对该项目进行的操作都会作为子节点存在与该根节点之下。对于每一个project节点，CC系统都会将其当作一个处理单元，并在最初建立该项目的时候进行初始化操作。&#xD;
&#xD;
  &lt;br /&gt;name是project节点常用的属性，也是必设且值唯一的属性，该属性的值会在整个CC系统使用，包括配置文件的${project.name}变量值。&#xD;
&#xD;
  &lt;br /&gt;在一个项目节点中，我们可以定义监听器、本地目录位置、变更轮询目录位置、轮询间隔、任务执行、单元测试、日志记录等多种项目操作，同时CC系统支持插件扩展功能，这些扩展插件可以直接在一个项目中使用。&#xD;
&#xD;
  &lt;br /&gt;&lt;strong&gt;2.3.1. 轮询版本控制系统&#xD;
    &lt;br /&gt;&lt;/strong&gt;版本库轮询机制是使用modificationset进行配置的。CC系统内置的轮询模块会根据设定的时间段对版本库进行检测，一旦发现版本库发生变更，就会调用Check Out Build Test Publish等一系列的操作，对最新的代码进行集成，并运行一系列预先设定的任务。&#xD;
&#xD;
  &lt;br /&gt;CC支持十多种版本控制系统，比如CVS、SVN、Starteam、VSS等，对这些版本控制系统的调用，只需要配置相应的节点名称即可。本文以SVN版本管理系统为例。在modificationset节中，我们看到唯一的一个子节点：&lt;/p&gt;&#xD;
&#xD;
&lt;pre&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;svn&lt;/span&gt; &lt;span style="color: #ff0000"&gt;localWorkingCopy&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;projects/CM/${project.name}/src/${project.name}&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;该节点使用了svn关键字，表示当前工程使用的版本控制系统是SVN，localWorkingCopy属性的值是告诉CC本地的拷贝目录，其余的工作则由CC内置的操作模块进行。&#xD;
  &lt;br /&gt;&lt;strong&gt;&lt;strong&gt;&lt;/strong&gt;2.3.2. 执行构建脚本&#xD;
&#xD;
    &lt;br /&gt;&lt;/strong&gt;实质上，执行构建脚本也是CC的一个可定制任务，但由于自动构建是持续集成的一个重要组成部分，因此在此单独提出。&#xD;
&#xD;
  &lt;br /&gt;CC的自动构建是使用ANT工具来进行的，当然我们也可以使用其它的自动构建工具来替代（比如Maven），这些的工具仅仅是体现在一个任务配置语句上，在此，以ANT工具为例。&#xD;
&#xD;
  &lt;br /&gt;在schedule节，我们同样使用了一个子节点来描述自动构建工作：&lt;/p&gt;&#xD;
&#xD;
&lt;pre&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ant&lt;/span&gt; &lt;span style="color: #ff0000"&gt;anthome&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;ant6&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;buildfile&lt;/span&gt;=&lt;span style="color: #0000ff"&gt;&amp;quot;projects/CM/${project.name}/src/${project.name}/build.xml&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;该节点使用了ant关键字，表示该任务使用了ant来进行自动构建任务，anthome属性则指定了ANT工具的具体位置，buildfile属性则指定了ANT进行自动构建所使用的配置文件Build.xml文件的路径。&#xD;
  &lt;br /&gt;这样，在CC决定进行自动构建任务时，会根据设定找到执行所使用到的信息。&#xD;
&#xD;
  &lt;br /&gt;&lt;strong&gt;&lt;strong&gt;&lt;/strong&gt;2.3.3. 执行单元测试&#xD;
&#xD;
    &lt;br /&gt;&lt;/strong&gt;CC可以自动侦测自动构建配置文件中单元测试的任务，并在代码集成完毕将执行结果反馈到相应的模块。&#xD;
&#xD;
  &lt;br /&gt;ANT支持xUnit系列的单元测试框架，只需要在配置文件中加入一个target节，即可在自动构建完成之后，进行单元测试工作，有关的详细配置，请参阅ANT官方文档。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2178250.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178250.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178247.html</id><title type="text">使用SVN+CruiseControl+ANT实现持续集成之一</title><summary type="text">在前面的文章中，介绍自己当时所在团队的处境(使用.NET开发)，一个不到十个人的研发团队在保证正常开发进度同时需要并发支持四、五十个项目问题处理，经常为了程序版本冲突、日常测试版本、发布版本提供等重复枯燥无味的手工劳动，导致团队成员身心俱疲。经历这样痛苦的一段时间，终于忍受不了，通过命令行实现了包括获取、编译、发布过程的集成，大大减轻版本编译的时间，此时还能见到团队成员一边编译程序一边聊天轻松的笑...</summary><published>2011-09-16T00:49:00Z</published><updated>2011-09-16T00:49:00Z</updated><author><name>HeroBeast</name><uri>http://www.cnblogs.com/HeroBeast/</uri></author><link rel="alternate" href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178247.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178247.html"/><content type="html">&lt;p&gt;在前面的&lt;a href="http://www.cnblogs.com/shishanyuan/archive/2011/08/11/2135107.html"&gt;文章&lt;/a&gt;中，介绍自己当时所在团队的处境(使用.NET开发)，一个不到十个人的研发团队在保证正常开发进度同时需要并发支持四、五十个项目问题处理，经常为了程序版本冲突、日常测试版本、发布版本提供等重复枯燥无味的手工劳动，导致团队成员身心俱疲。经历这样痛苦的一段时间，终于忍受不了，通过命令行实现了包括获取、编译、发布过程的集成，大大减轻版本编译的时间，此时还能见到团队成员一边编译程序一边聊天轻松的笑脸，这就坚定了自己持续集成的做法，不过可笑是当时自己对持续集成没有任何的概念，只是当时的状况逼自己走了集成之路。    &lt;br /&gt;这个工具在经历半年使用进行了一次升级，提供了更多的选项功能，参见&lt;a href="http://www.cnblogs.com/shishanyuan/archive/2011/08/25/2153384.html"&gt;升级版本&lt;/a&gt;介绍。另外随着公司业务的发展，2009年自己负责推出一个基于JAVA的产品平台，这个平台中包括了七八个子系统。一个困难就出现在我们面前，为了保持以前每周一次发版，每次编译发布都需要两三个小时，为了摆脱这种困局找了很多资料，学习了很多新的思想，对比了很多工具，最终使用了基于CruiseControl(以下简称CC)实现持续集成。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;1. 持续集成概念&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;对于持续集成（Continuous Integration）这个术语源自 XP（极限编程）的一个最佳实践，随着XP近几年的推广持续集成被大家认可并实践，但持续集成并非 XP 的专利，持续集成完全可以应用在采取非XP 方法的项目里面。持续集成也不是一个新的概念，在这个术语出现之前，日创建（daily build）提供同样的含义，这个典型的代表就是微软，他们每天的工作都开始于每日零点的版本构建。持续集成和日创建主要区别就在于实施的频率上，随着 XP 社区的大师级人物 Martin Fowler等人所著《Continuous Integration》为其正名，持续集成这个术语就越来越多地出现在原来日创建出现的位置。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2. 持续集成优点&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在传统开发模式中项目按照模块进行划分，等开发完成后再集成到一起进行测试，这种开发方法在小规模程序开发过程中并没有太大的不足。但随着软件技术的发展，软件规模也在扩大，软件需求越来越复杂，软件已经不能简单地通过划分模块方式来开发，因为很多Bug在项目早期就存在了，如果在最后集成的时候才发现问题，开发者需要在集成阶段花费大量的时间来寻找Bug，由于软件的复杂性，需要花费大量的时间进行定位，甚至有些需要调整底层架构。在这个阶段的除虫会议（bug meetings）特别多，会议的内容基本上都是讨论 bug 是怎么产生的，最后往往发展成为不同模块的负责人互相推诿责任。   &lt;br /&gt;持续集成最大的优点是可以避免这种传统模式在集成阶段的除虫会议。持续集成主张项目的开发人员频繁的将他们对源码的修改提交(check in)到一个单一的源码库，并 验证这些改变是否对项目带来了破坏，持续集成包括以下几大要点：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;访问单一源码库，将所有的源代码保存在单一的地点（源码控制系统）， 让所有人都能从这里获取最新的源代码，提倡开发人员频繁提交修改过的代码。 &lt;/li&gt;    &lt;li&gt;支持自动化创建脚本，使创建过程完全自动化，让任何人都可以只输入一条命令或者几次点击就完成系统的创建。 &lt;/li&gt;    &lt;li&gt;测试完全自动化，要求开发人员提供自测试的代码，让任何人都可以只输入一条命令或者几次点击就运行一套完整的系统测试。 &lt;/li&gt;    &lt;li&gt;支持自动化部署，能够按照不同的要求发布到测试、发布服务器，提供测试环境和发布程序包； &lt;/li&gt;    &lt;li&gt;自动提供集成信息，按照不同情况提供通过邮件、报告等方式提供每次集成结果，并且提供发布平台大家能轻易看到集成的进度和结果&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;持续集成的关键是完全的自动化，自动读取源代码、编译、测试、部署、信息发布。对于每次成功的创建，要求在这个自动化过程中的每一步都不能出错，而最重要的一步是测试，只有最后通过测试的创建才是成功的创建。   &lt;br /&gt;在持续集成里面创建不再只是传统的编译那么简单，创建还应该包括自测试，自测试的代码是开发人员提交源码的时候同时提交的，是针对源码的单元测试，将所有的这些自测试代码整合到一起形成测试集，在所有的最新的源码通过编译之后还必须通过测试集的测试才算是成功的创建。这种测试的主要目的是为了验证创建的正确性，McConnell 称之为“冒烟测试”，在持续集成里面，这叫做集成验收测试Build Verify Test，简称 BVT。BVT 测试是质量的基础，QA 小组不会感受到 BVT 的存在，他们只针对成功的创建进行测试（如功能测试）。    &lt;br /&gt;持续集成有一个与直觉相悖的基本要点，那就是“ 经常性的集成比偶尔集成要好”。Martin Fowler 认为对于持续集成来说，集成越频繁，效果越好 ，如果你的集成不是经常进行的（少于每天一次），那么集成就是一件痛苦的事情，如果集成偶尔才进行一次（一周甚至一个月）， 等到集成阶段发现bug，然后找原因解决bug，会耗费你大量的时间与精力，而且这种方式有点像传统的集成模式，这违背了持续集成的初衷。    &lt;br /&gt;根据 Martin Fowler 的观点，项目 bug 的增加和时间并不是线性增长的关系，而是和时间的平方成正比，两次集成间隔的时间越长，bug 增加的数量越是超过你的预期，解决 bug 付出的工作量也越大，而你越觉得付出的工作量越大，你就越想推迟到以后去集成，企图到最后一次性解决问题，结果 bug 产生的就更多，导致下一次集成的工作量更大，你越感觉到集成的痛苦，就越将集成的时间推后，最后形成恶性循环。    &lt;br /&gt;需要注意的是从项目的一开始就引入持续集成可以尽早的发现 bug，但是并不代表持续集成可以帮你抓到所有的 bug。持续集成的排错能力取决于测试技术，众所周知，无法证明已经经过测试的代码就已经找到了所有的错误。    &lt;br /&gt;前面列举了持续集成这么多优点，但是创建一个持续集成的环境技术上是比较复杂的，也需要一定的时间，关键是在于持续集成可以“及时”抓到足够多的 bug，从根本上消除传统模式的弊端，这就已经值回它的开销了。    &lt;br /&gt;ThoughtWorks 公司开放了其持续集成的工具CC的源代码，持续集成对于大部分开发人员来说就不再只是停留在口头上的漂亮的术语，任何人在掌握了持续集成的基础理论后，都可以使用CC来体会持续集成在项目开发中的巨大威力。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3. 集成框架&lt;/strong&gt;&lt;strong&gt;     &lt;br /&gt;&lt;/strong&gt;下个图描述持续集成的硬件环境，图中包括了一台独立的源码库服务器以及开发人员的终端（同时也是源码库服务器的客户端），出自对性能的考虑，建议CC 在一台独立的服务器上运行。当然你可以将 CC 放在发布服务器上甚至某个开发人员的终端上。&lt;/p&gt;  &lt;p&gt;&lt;img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_1/image001.jpg" width="593" longdesc="" height="647" /&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;4. CC内部工作架构&lt;/strong&gt;&lt;strong&gt;     &lt;br /&gt;&lt;/strong&gt;下图是CC系统内部工作架构图：&lt;/p&gt;  &lt;p&gt;&lt;img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_1/image003.png" width="750" longdesc="" height="431" /&gt;    &lt;br /&gt;CC主要依赖Build Loop循环构建实现，通过读取Config.xml配置文件信息，在每次轮询中完成源代码的检测、编译，然后把编译的版本发布Web容器中，以此同时把日志信息、发布结果通过RSS、邮件、网站等形式发布给干系人。    &lt;br /&gt;&lt;strong&gt;4.1. Build Loop     &lt;br /&gt;&lt;/strong&gt;前面在讨论持续集成的时候讲到其最重要的特征之一是自动化，而 CC 的 Build Loop 就是为支持自动化而设计的，Build Loop 也是 CC 的核心。    &lt;br /&gt;Build Loop 从字面上理解就是循环创建的意思，CC 提供了一个守护进程( daemon)，该进程自动根据配置的时间间隔（也可以指定某个具体时间）读取 CC 配置文件并进行循环创建（build cycle），每次 CC 都会重新加载配置文件（修改了配置文件不用重新启动 CC）。    &lt;br /&gt;Build Loop 过程中所做的工作如下：访问源码控制系统，查看是否有代码被修改，如果有，获取源码的新版本，并根据配置对源码进行一次 Build，创建一个日志文件，最后向开发人员通知 build 的结果，活动图如下：&lt;/p&gt;  &lt;p&gt;&lt;img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/shishanyuan/DailyBuild/CruiseControl_1/image005.jpg" width="300" longdesc="" height="466" /&gt;    &lt;br /&gt;因为 Build Loop 是根据配置文件的内容来进行的，根据上面 BuildLoop 所做的工作，我们可以猜出配置信息主要应该包括：定时创建的时间和源码库的访问信息（检查源码变化情况），创建任务信息（如指定 Ant 文件）， 记录日志（创建结果），通知（通知的内容可以定制）。    &lt;br /&gt;&lt;strong&gt;4.2. CC 插件（Plugin）     &lt;br /&gt;&lt;/strong&gt;CC 设计思想是one-size-fits-all，也 就是CC 是由一个很精小（ 但是很强大）的核心（ Build Loop）以及一些外部插件组成，这给使用者提供了很大的扩展空间，使用者可以根据需要扩展 CC的功能（提供新的插件），而且 CC 是开源项目，你还可以查看源码并修改CC提供的插件。CC提供了六种不同类型的插件：Listener、Bootstrappe、Modificationset、Schedule、Log以及Publisher，CC 的配置是围绕这些插件展开的，下面对这些插件进行一个简单的介绍：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Listener：用于处理一些项目有关的事件； &lt;/li&gt;    &lt;li&gt;Bootstrapper：在 CC 进行创建之前运行，是创建前的准备工作 &lt;/li&gt;    &lt;li&gt;Modificationset：访问源码控制系统（如 CVS，VSS，ClearCase 等等），查看源码自上一次 Build 之后是否被修改过，并据此决定是否需要进行下一次 Build。 &lt;/li&gt;    &lt;li&gt;Builder：对项目进行创建，熟悉 ANT 的使用者应该很清楚创建的含义，这里简单提一下，一次典型的创建包括了对项目源码的编译，测试，打包 &lt;/li&gt;    &lt;li&gt;Schedule：设置轮询时间并且指定使用ANT编译所使用的配置文件地址 &lt;/li&gt;    &lt;li&gt;Publisher：用于发布创建的结果，可以通过 email 的方式通知开发人员。&lt;/li&gt; &lt;/ul&gt;&lt;img src="http://www.cnblogs.com/HeroBeast/aggbug/2178247.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/HeroBeast/archive/2011/09/16/2178247.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
