其他 配置管理工具迁移到IBM Rational公司的ClearCase UCM配置管理 解决方案 的一些经验。 1.2 概念 在使用Cl" name="description" />

ClearCase迁移中的一些经验

发表于:2007-04-29来源:作者:点击数: 标签:clearcase迁移中的一些经验
1 简介 1.1 目的 本文的目的是介绍某公司在将软件资产从 java script:;" onClick="javascript:tagshow(event, '%C6%E4%CB%FB');" target="_self"> 其他 配置管理工具迁移到IBM Rational公司的ClearCase UCM配置管理 解决方案 的一些经验。 1.2 概念 在使用Cl

1 简介

1.1 目的
本文的目的是介绍某公司在将软件资产从javascript:;" onClick="javascript:tagshow(event, '%C6%E4%CB%FB');" target="_self">其他配置管理工具迁移到IBM Rational公司的ClearCase UCM配置管理解决方案的一些经验。

1.2 概念
在使用ClearCase之前,必需理解某些概念:

  • Element 纳入配置管理的包括版本信息的配置项,包括文件与目录。
  • VOB Version Object Base,存放配置项的库。
  • UCM Unified Changed Management的缩写,统一变更管理模式
  • Activity Activity是ClearCase UCM模式中的一个概念,通过变更集(Change Set)跟踪完成一项开发任务所引起的所有配置项的变更。在UCM模式下所有的Check Out、Check In、Add to Source Control等引起配置项发生变化的操作必须关联到一个Activity。
  • Change Set Change Set记录了Activity所关联的所有的配置项的版本变更,每个Activity都有一个Change Set。
  • Component 可以理解为一些代码、文档、Model等按一定的目录结构组织成的完成某些功能的可以重用的集合。这是UCM所引入的概念,Component与UCM Project相关联,UCM Project所管理的所有的Element必定从属于一个Component,每个UCM Project至少有一个Component。
  • Deliver UCM的概念,是一个从开发流向UCM Project集成流或其他开发流提交工作的一个动作。
  • Development Stream UCM的概念,可以理解为一个独立的开发环境,包含了在这个开发流上的Activity与修改的配置项的版本,UCM通过开发流简化了并行开发的配置管理工作。
  • Dynamic View Dynamic View是对VOB的一个动态视图,VOB的变化会及时反应到Dynamic View上,每个Dynamic View都关联到一个Stream上,在Dynamic View上会有一些View的私有文件,这些View私有文件不会被同一个Stream上的其他View所见到。
  • Integration Stream UCM的概念,可以理解为项目的主干,每个开发流都是集成流的一个分支,在开发流上完成工作后,再提交到主干,项目的Build环境建议采用集成流
  • Project 是ClearCase UCM的一个概念,包含了配置管理所需要的一些配置信息,如果Component、Baseline,Stream等,每个Project都有一个Integration Stream。
  • Project VOB(PVOB) 是存储UCM所需要的一些特殊的信息,如Proejcts,Stream,Activity及Change Sets等,一个PVOB可以包含多个Project的信息, Project的信息必须保存在PVOB中。
  • Rebase UCM模式的一个操作,让当前Stream的View的内容与Integration Stream推荐基线同步。
  • Snapshot view Snapshot View是对VOB的一个静态视图,将相关的VOB的选定的版本下载到本地保存,需要经常进行Update View操作以保证与关联的stream同步。
  • Add to Source Control 执行将选定的文件或目录纳入ClearCase管理的动作,需要注意的是,如果要在某一目录下添加文件或目录,必须先将它所在的目录先Check out,再在该目录下执行Add to Source Control动作,而后再对当前目录执行Check in;如果正确执行完成后,该文件与目录后的类型会变为File element Version或Directory Version,如果没有将当前目录Checkout就执行Add to Source Control,则在执行完成后文件的类型还是View-private File或View-private Directory,在这种情况下,该文件或目录实际上没有纳入配置管理。

2 计划与准备

2.1 计划
配置管理切换大至可以划分为以下几个阶段:计划,准备,配置库的迁移,正式使用。

配置管理切换计划的主要内容包括进度、资源等。

项目的规模与所处的阶段不同,则配置管理切换所需要的时间也不同。一个20人左右,开发进度约达到计划的一半,代码量达到50K左右的项目,从开始计划到配置管理完全切换到ClearCase,最少需要3-4周时间。如果盲目的追求进度,想在1-2周内切换完成,则可能在切换后产生一系列后遗症,如版本丢失、版本错误甚至可能会有部分项目组成员抵制,从而使项目开发进程中部分工作不能纳入配置管理之下。

进度安排建议:根据项目的情况用5-15个工作日进行准备,配置库的迁移需要5个工作日左右的时间,配置管理工程师要用5-10个工作日的跟进以使项目组成员熟悉并不再需要帮助。

任何计划都有一个前提:资源,不同的资源会导致不同的进度与成本。在配置管理切换中三类资源非常重要:经过培训并且有ClearCase经验的配置管理工程师;经过培训并了解ClearCase UCM概念的项目经理与架构师;Rational工程师的及时支持。

配置管理工程师在这3-4周时间内要没有其他的任务的打扰,全部的时间应用于该项目的配置切换;每个项目在配置切换的准备阶段如果有Rational工程师的现场支持会少走许多弯路。

为了更好的完成工作,配置管理工程师必须经过系统的ClearCase的培训,同时为了提高配置管理工程师的能力,建议在内部建立一个独立的试验环境,可以让配置管理工程师从安装配置Server开始,进行ClearCase的各种功能的操作试验,以获得经验。

2.2 准备
如果决定应用ClearCase,好的计划与充分的准备会起到事半功倍的效果。一个项目从启动就应用ClearCase则相对于从其他配置管理解决方案迁移到ClearCase在准备上要容易的多,包括多个版本分支的产品的配置迁移则更加困难,如果准备不充分,可能会造成多次反复、严重降低工作效率,甚至可能会造成版本错误等严重后果。

首先,要决定是应用ClearCase UCM还是Base ClearCase,UCM模式是基于Base ClearCase应用Activity管理变更的一种模式。如果项目组全部在UNIX上进行开发,比较熟悉CVS,对命令行及Shell很熟悉,项目团队配合时间较长,有专职配置管理工程师,建议应用Base ClearCase,但是需要自行开发脚本,以利于项目组成员的使用;跨平台项目、配置管理工程师是与其他项目共用的、需要对项目的进度与活动有较高的透明度等建议应用UCM模式。本文主要探讨UCM模式。

在准备的时候要确定当前项目与其他的项目的关系,以确定PVOB的建立,如果项目和其他项目的关系不是很紧密,建议创建一个独立的PVOB。因为一般PVOB不占用过多的资源。

2.2.1 配置模式

PVOB建立完成后,要根据项目的实际情况确定项目的开发模式,这里给出一些建议。

2.2.1.1 共享流模式

项目只有一个单独的集成流,没有开发流。适用于调研项目或规模较小,且目标单一,不会同时有多个变更存在的项目。比较大的项目也可以在实际项目的初始阶段建立一个UCM Project,采用共享流模式,在需求完成后,在这个Project的Component上建立Final基线,在这个基线上建立一个新的多开发流模式的UCM Project进行设计与编码。

优点:控制简单,如果设置的是Dynamic View,每个人的修改,其他人可以立即看到,不需要deliver,对有大量文档的项目较适合;不需要针对Deliver及Rebase设置大量的基线,配置管理人员的工作相对较少;同时项目配置管理的Policy也比较简单,不需要考虑太多。

缺点:如果同时支持多个不同的客户或同时有多个变更,这些变更之间互相影响,则会产生开发的混乱。

在Clearcase中共享流模式也支持同时多个用户对同一文件进行Check out操作,并在Check in时进行归并。但是如果多人对一个Element进行Check out操作时,只有一个人可以应用Reserved checkout,其他的项目组成员只能进行Unreserved Checkout。Reserved Checkout保证了开发人员是在最新的一个版本上进行Checkout,只有在Reserved Checkout的人Check in之后才可以Check in并进行归并。Reserved与Unreserved的区别可见图一。


图一:两种Check-Out方式

2.2.1.2 多开发流模式

项目中有多个不同的开发流,每个开发流都是一个独立的分支,如果项目需要还可以建立多层次的分支,支持并行开发,适于超过10人,较复杂的项目。如果项目极复杂,可以分为多层开发流与集成流,如图二。优点:可以并行开发,每个Stream都相当于一个独立的开发环境,每个人之间的工作不会互相产生干扰;可以通过Policy的设置更好的进行配置管理。

缺点:不同的Stream之间的Deliver与Rebase会产生问题;在merge时也有可能会产生问题,而且对Word等二进制文件的merge支持不好;在修改完成之后,每个Stream上的修改只有deliver与Rebase才能被其他的stream应用,不能及时反映变化;Policy的设置较复杂。

在多开发流模式下可以根据需要将某个stream设置为只读模式。

建议:可以根据需要建立一个多开发流模式的Project,但是在初期阶段不设立开发流,在进行详细设计阶段后再建立相应的开发流。


图二:多开发流模式示例

2.2.1.3 Project组模式

Project组模式是以上两种模式的组合,适用于产品类项目,在这种类型中,设立一个主干Project,针对不同的客户或不同的变更,在相应的baseline上建立新的共享流Project去处理,而不是在多开发流中的Project新建一个开发流。如果其中某个客户的要求或变更比较复杂,也可以建一个多开发流的Project进行处理。

优点:可以根据任务的实际情况灵活处理变更等,而且如果发现对所有用户都需要的变更可以在主干上修改并发布到各个子Project上,也可以在一个子Proejct上修改,经验证后再发布到其他子Project,对于有长远规划的产品非常适合。

缺点:如果在最初架构师考虑不周,Component划分不合理在后期会比较困难;不同Project之间的Deliver需要更复杂的Policy,需要配置管理工程师极有经验。


图三:Project组模式示例

2.2.2 Activity的命名准则

建议对不同类型的工作可以通过Activity的命名直接区分,建议如下:

新加功能为:Feature_功能名

变更的执行:CR_变更号
注:如果变更中涉及到文档的修改,则文档修改也应用此Activity

修改Bug:Bugfix_BUG
注:BUG号来自ClearQuest

文档:Doc_文档名
注:在变更及Bugfix中文档的修改activity应用变更的activity

计划的更新:Plan_Tracking_时间
另一建议为选用ClearQuest为缺陷管理工具,并将ClearCase与ClearQuest集成,这样所有的Activity可以通过ClearQuest获得。

2.2.3 Deliver与Rebase的准则

项目中需要明确Deliver与准则,包括什么情况下可以Deliver,Deliver前是否全部文件都Check in,是否可以向非本项目的Stream进行Deliver等,这些需要根据实际情况确定,但是为了尽量避免冲突,建议在Deliver前要求进行Rebase。

2.2.4 配置存储的逻辑视图与物理视图

项目经理、架构师与配置管理工程师要一起确定项目配置的逻辑视图,配置管理工程师要根据情况确定配置的物理视图。ClearCase的UCM模式中的Component可以理解为配置的逻辑视图,而VOB的设置可以理解为配置的物理视图。

2.2.4.1 配置存储的逻辑视图:Component

Component可以从系统的架构导出,如果应用RUP或项目有Deploy View或Implementation View则可以从中导出Component。

大多数从其他配置管理工具切换到ClearCase的项目将所有的代码作为一个Component,这样虽然简单,但是就失去了使用ClearCase的意义,可以按模块或3-Tier架构来分解代码,这样也利于项目组成员理解项目。Component的主要作用就是用于重用;设置Component的另一个目的是代码的权限控制,如果有外包或实习生一同工作,可以将核心代码设置为一批Component,将可以由外包或实习生接触的代码设置为一批Component,通过对Component的权限进行设置,可以防止恶意获取或修改代码的可能性。

文档可以按以下两种方式进行管理:

  • 单独设置一个文档VOB,所有的文档都放在一起,优点是权限控制简单,可以将文档提供给其他人员而不用担心代码的泄漏,缺点是代码与文档分离,工作中可能会出现两者不一致的问题。
  • 根据架构,同一模块或Tier的代码与相应和文档一个Component中,优点是可以保证文档与代码的一致性,但是这时要保证代码与文档的安全性要繁琐一些。

Rational公司给出了Component及目录的设置,可以参考。


2.2.4.2 配置的物理视图

Component只是ClearCase UCM模式的逻辑视图,而实际的存储与控制是由VOB实现的,通过对VOB的访问控制实现对Component的控制。从安全与实用的角度出发,建议每个项目的VOB独立,不要几个项目共用一个VOB。如果一个项目非常重要,对代码等软件资产的管理要求严格,建议将文档、核心代码、非核心代码分别设置为三个VOB,这样可能对Server的硬件资源较高,但是安全上带来的好处足以弥补硬件上额外的开支。Component可以是VOB或VOB的一个子目录,需要注意的是VOB只有第一级子目录才可以设置为Component。

在不同的PVOB中可以Import同一个VOB或其子目录作为Component,但是这时一定要注意,并规划好各分支的关系。

2.2.5 配置库安全设置

配置模式、项目配置的逻辑视图与物理视图确定之后,配置管理工程师要和项目经理一起确定配置库及配置项的安全设置。ClearCase的安全设置和Winodws、Unix系统相关,在本文只介绍Windows下的设置。

ClearCase中Windows域中有一个特殊用户clearcase_albd,Clearcase系统要求对所有的VOB与View共享目录,该用户均有完全控制权限,所以该用户的安全非常重要;而且由于在每个客户端中设置了Atria Location Broker服务,该服务是以域用户clearcase_albd启动,所以如果修改clearcase_albd用户的密码,需要变更每个客户端的密码(见图)。建议该用户密码至少12位,要为无意义的字符串,要包含数字、大小写字母与特殊字符。


ClearCase的安全设置有三个部分:

  • 配置库存储目录的安全设置
  • 配置库的安全设置
  • 配置项的安全设置

以上的所有安全设置都是基于windows域的安全组,项目经理要根据项目的人员分布与代码保密的原则确定人员的分组,明确不同组的人员的代码权限,配置管理工程师负责与域管理员联系建立用户与组。

从工作的方便性与软件资产的保护原则出发,建议每个项目设置一个quality组,项目经理、配置管理工程师与质量经理是该组的成员。

在ClearCase的VOB服务器上需要建立一个共享目录用于存放用户共同访问的VOB的物理实体。

该共享目录的权限设置为所有的开发人员都有读写权限。为了保证VOB实体的安全性,在该共享目录之下要设立另一个目录用于直接存放VOB的物理实体,对所有的开发人员是读写权限,对配置管理工程师、clearcase_albd需要设置为完全控制权限,该部分设置一般不需要进行,在create VOB及应用命令cleartool protectvob时,ClearCase会自动设置。

VOB实体的属性中包括owner,group与additional group,owner表示谁拥有该VOB,group表明该owner是哪个组的,additional group描述了还有哪些组对该VOB具有操作的权限。如果在配置项中设置了其他组可读,但是如果用户的组没有在group或additional group中则用户无法获得配置项,这样可以保护一些核心代码等,所以建议核心代码单独设置为一个VOB。VOB的权限设置可以通过命令行来进行设置:

cleartool protectvob

具体的使用方法可以用cleartool man protectvob获取帮助。

配置项的安全设置类同UNIX。需要注意的是在ClearCase中目录也是作为配置项进行管理的。在使用中要注意的是ClearCase的GUI界面不支持递归,所以如果想修改某一目录及之下所有子目录的权限设置,请应用命令行进行。


2.2.6 环境的准备

图五:配置系统架构图
图五:配置系统架构图

上图是Rational建议的服务器的配置的逻辑视图。以下是一些要求:

  • 网络要求
    ClearCase支持客户/服务器(C/S)以及浏览器/服务器(B/S)两种使用方式,要求客户机和服务器通所在的网络环境支持TCP/IP,局域网均能满足要求,建议100兆以太网。
  • 操作系统要求
    如果在Windows环境下部署ClearCase,首先应满足ClearCase要求的平台条件(如Windows2000需SP2以上等),其次需要所有开发机器均在要加入Windows域以进行统一的用户校验和安全性管理。如果在Unix环境下部署ClearCase,同样需满足ClearCase要求的Unix条件(如打上ClearCase需要的操作系统补丁等)。
  • 硬件要求
    Windows环境下,VOB Server建议CPU P3-1GHz以上,内存512MB以上,硬盘空间80GB以上,如果有可能,最好采用服务器。

如果单纯从性能考虑,VOB Server最好采用UNIX系统,但是在实际情况中要考虑到易用性等,如果项目组成员大多数采用Windows平台进行开发,建议还是使用Windows系统做为VOB Server,因为如果采用UNIX VOB Server,如果想在Windows平台上使用Dynamic View会有一定的困难。

在实际中可以将VOB Server与License Server及Registry Server配置在一台机器上。这些Server中只有VOB Server与View Server的对配置的要求比较高,而且一个Registry Server上只能启动一个Windows Region与UNIX Region,所以建议每个项目配置一个Registry Server,配置项目自己的Region。

在实际使用过程中,最初所有的View均保存在项目组成员的机器上,但是在使用中出现一系列问题,如果项目足够的资源,建议配置一个独立的View Server,项目组成员的所有Dynamic View要求必须建立在View Server上。

在环境的准备过程中,要考虑到开发人员的开发习惯与测试环境等问题,决定VOB Sever是安装在Windows平台还是安装在Windows平台。在决定安装平台后,要根据开发模式确定是否安装Web Server,如果项目会有大量的在外支持的工作,并要求在客户现场修改代码,建议安装在办公网段,这样可以通过外网进行访问;如果是产品项目在公司内部研发,没有远程修改的需求,建议安装在实验网段。

在Server安装完成后,要根据代码保密与配置管理等原则等将所有的用户与用户组在域中建立,并将网络安装包共享给用户使用,要注意有是在某个域上安装了ClearCase客户端后,并不能直接在另一个域上使用,需要修改Atria Location Broker这个服务中启动用户与密码,所以在安装完成后,不能对clearcase_albd的密码进行改动,所以clearcase_albd这个用户设置中一定要注意设置密码永不过期。如果一个项目组成员想在不同的域并且这些域之间没有信任的情况下都使用ClearCase,只能安装两套操作系统,在每个系统上都安装ClearCase客户端。

2.2.7 旧版本的整理与版本的迁移

在服务器安装完成后,要考虑旧版本的整理,如果只是简单的将VSS与CVS的全部配置项移到ClearCase中去,就只是将ClearCase当做VSS与CVS使用,使用ClearCase也没有什么意义,所以要将旧有的配置项进行整理。这项工作应在配置库的逻辑视图与物理视图确定之后就开始,一直持续到版本的迁移。

在整理旧有的配置项时要先将原有的VSS或CVS配置库进行备份,而后在备份的配置库进行整理,以防止对工作中的配置库造成损坏。版本整理的时候可以将文档与代码重新按照Component结构设置。

在VSS中为了工作方便,常常将工作库,受控库与基线库分离,而且VSS的分支功能并不是很好,针对不同的客户修正一般都会新建一个目录来进行修改,同一个配置项在配置库中存在多个副本,为配置管理带来许多人为的不可控因素。

在整理VSS配置库时,一般情况下文档部分可以只采用Get last version的方法,取出最新版本,按规定放入Component即可;代码的处理有所不同,如果所有的代码在VSS配置库中只存放在一处,之后在此基础上设置label,则可以应用命令clearexport_ssafe与clearimport将其导入,在导入结束后将所有的label导入到相应的Component上即可;如果有多处副本只能将每处副本的相应基线应用get last version命令取出,而后将用clearfsimport导入Clearcase,之后在相同目录下重复以上动作,要注意的是每次clearfsimport后要建立一个基线。

针对一些有长年积累,在VSS上有多个目录存放不同的版本的项目,不要有必其功于一役的不切实想法,应先整理以前的版本,找出几个主要版本树,将各个版本之间的关系理清楚,之后将几个版本树按以上的方法导入。

如果源代码在原项目中是应用CVS进行配置管理,一般情况下,在CVS中没有副本存在,可以应用clearexport_cvs命令与clearimport命令导入好可。

在应用clearimport时要注意,如java中文件名是区分大小写的要应用clearimport -p,具体方法可以应用cleartool man clearimport来查看帮助。

2.2.8 客户端的安装与培训

每个项目在安装时要根据安装手册制定本项目自己的安装手册,根据项目实际情况修改后发布给项目使用。在所有的客户端安装后,项目配置管理工程师要准备培训材料对项目组成员进行培训,培训中要讲清楚项目的PVOB、开发模式、Component的设置、分组与权限的设置、Stream的设置、项目配置的Policy、Activity的命名准则、Deliver与Rebase的要求等实际情况,而不是只讲共性的一些东西。

2.2.9 试用

如果大部分项目组成员以前没有过ClearCase的使用经验且进度允许,则在客户端安装及培训完成后,要在项目组内部进行试用,以让项目组成员熟悉;最好是ClearCase与VSS或CVS并行使用一周左右时间,然后再将配置管理完成切换到ClearCase。

3 VSS迁移的步骤

3.1 一些前提条件
3.1.1 软件安装

必须在ClearCase的VOB端安装VSS服务器程序。

3.1.2 用户权限

对于Visual Source Safe,要以对Visual Source Safe系统中所有工程/文件均具有完全权限的身份操作;

对于ClearCase一侧,要ClearCase管理员的身份操作;

因此在迁移时,最好选用同一个帐号(口令亦相同),同时具有以上两个权限。

如果你的ClearCase帐号不具有以上权限,请与你的系统管理员联系。

3.1.3 日期/时间格式

在迁移过程中,ClearCase对时间要求比较严格,且用到的是短时间格式,具体设置如下:

1、 打开控制面板的区域设置属性;

2、 在时间栏中,将时间样式设为"h:mm:ss tt";
将时间分隔符设为":";
将上午符号设为"AM" ;
将下午符号设为"PM" ;
注意以上设置值的大小写!

3、 在日期栏中,将短日期样式设为"M/d/yy";
将日期分隔符设为"/" ;
设置完后可查看资源管理器中文件的时间属性以检查上述设置的正确性。正确的修改应为:5/21/01 11:00 AM

3.1.3.1 环境变量

为方便操作,可添加以下系统环境变量:


cccccc border=1>

变量名PATH    
变量名 ??\Microsoft Visual Studio\vss\win32; //VSS中ss.exe路径??\rational\clearcase\bin;
             ??\rational\clearcase\etc; //ClearCase中clearexport_ssafe.exe路径
以上??用户实际应用程序路径。
设置ssdir环境变量为vss数据库文件的路径;
设置ssuser环境变量为vss登录用户名(为方便使用,可将该用户的密码设为空).

ss dir: 显示当前的Project;
ss cd $/SW:设置当前的Project为SW;
ss whoami:显示当前的登录用户;

设置完毕后,可在命令行界面下运行path查看以上设置是否生效。

3.2 建立VOB
建立VOB需要注意的是当前的用户与主组,建立用户时的用户与主组就是VOB的Owner与Group,但是有时会出现用户的主组并不是所期望的Group,这时可以应用命令修改vob的owner与group。



cleartool protectvob -chown user -chgrp group -r VOBPNAME

3.3 建立General View
在建立VOB可以建立general view,以后所有的迁移都是在general view下进行的,这时可以不必关心view的owner。在建立View时要注意一定要将View建立为Dynamic View,并映射为本地的一个盘符,在稍后的操作中所有的操作都是以命令行方式进行。

3.4 备份要迁移的VSS配置库到VOB所在的机器
备份的目录主要是可以根据迁移的需要对目录进行修改,而不会影响VSS配置库,所有的迁移的操作都是针对备份到VOB所在机器的配置库进行的。

3.5 设置VSS的工程目录
进行命令行模式,执行ss cp获得当前的工程目录,如果不是要迁移的目录执行ss cp $/要迁移的目录/,注意这时迁移的是当前目录的子目录,如果想包括当前目录,请到当前目录的上一级目录,这时如果只想备份上一级目录的部分子目录可以将其他目录删除,这时就可以看到用备份的VSS配置库进行操作的好处了。

3.6 生成迁移所需要的文件
VSS的工程目录确定后,执行clearexport_ssafe -r -o生成迁移所需要的文件。例:



Clearexport_ssafe -r -o e:\test\exportdata

3.7 迁移
进入general view所对应的映射盘,进入VOB所在的目录,如VOB名为Test_VOB,general view映射为Y盘,则cd y:



cd \Test_VOB

确定是否迁移到当前目录,如果要建立子目录要注意,用命令行建立的子目录实际并没有在VOB中建立,要在Rational explorer中建立子目录,并确认子目录的类型为Directory Element才可以。

进入要迁移的目录后执行clearimport e:\test\exportdata,注意如果是java等代码要区分大小写,要加参数clearimport -pcase e:\testexportdata

3.8 后续步骤
将当前数据迁入后打一个label,并Apply;将VOB或其子目录Import为Component,而后在Component上执行Import Baseline,将刚打的label引入即可。


原文转自:http://www.ltesting.net

...

热门标签