??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品字幕在线观看,久久精品亚洲中文字幕无码麻豆,亚洲狠狠久久综合一区77777http://www.tkk7.com/obpm/category/46135.htmlzh-cnThu, 23 Jun 2011 15:01:05 GMTThu, 23 Jun 2011 15:01:05 GMT60接口和抽象类的区别(转蝲Q?/title><link>http://www.tkk7.com/obpm/archive/2010/11/07/337451.html</link><dc:creator>obpm</dc:creator><author>obpm</author><pubDate>Sun, 07 Nov 2010 05:57:00 GMT</pubDate><guid>http://www.tkk7.com/obpm/archive/2010/11/07/337451.html</guid><wfw:comment>http://www.tkk7.com/obpm/comments/337451.html</wfw:comment><comments>http://www.tkk7.com/obpm/archive/2010/11/07/337451.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.tkk7.com/obpm/comments/commentRss/337451.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/obpm/services/trackbacks/337451.html</trackback:ping><description><![CDATA[从设计理念层面看abstract class和interface <br /> <br /> 上面主要从语法定义和~程的角度论qCabstract class和interface的区别,q些层面的区别是比较低层ơ的、非本质的。本节从另一个层面:abstract class和interface所反映出的设计理念Q来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概늚本质所在?<br /> <br /> 前面已经提到q,abstarct class在Java语言中体C一U承关p,要想使得l承关系合理Q父cdzcM间必d?is a"关系Q即父类和派生类在概忉|质上应该是相同的Q参考文献?〕中有关?is a"关系的大幅深入的论qͼ有兴的读者可以参考)。对于interface 来说则不Ӟq不要求interface的实现者和interface定义在概忉|质上是一致的Q仅仅是实现了interface定义的契U而已。ؓ了便于理解Q下面将通过一个简单的实例q行说明?<br /> <br /> 考虑q样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Doorh执行两个动作open和closeQ此时我们可以通过abstract class或者interface来定义一个表C抽象概念的类型,定义方式分别如下所C: <br /> <br /> 使用abstract class方式定义DoorQ?<br /> <br /> abstract class Door { <br /> abstract void open(); <br /> abstract void close()Q?<br /> } <br /> <br /> <br /> 使用interface方式定义DoorQ?<br /> <br /> <br /> interface Door { <br /> void open(); <br /> void close(); <br /> } <br /> <br /> <br /> 其他具体的Doorcd可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看h好像使用abstract class和interface没有大的区别?<br /> <br /> 如果现在要求Doorq要h报警的功能。我们该如何设计针对该例子的cȝ构呢Q在本例中,主要是ؓ了展Cabstract class和interface反映在设计理念上的区别,其他斚w无关的问题都做了化或者忽略)Q下面将|列出可能的解决Ҏ(gu)Qƈ从设计理念层面对q些不同的方案进行分析?<br /> <br /> 解决Ҏ(gu)一Q?<br /> <br /> 单的在Door的定义中增加一个alarmҎ(gu)Q如下: <br /> <br /> abstract class Door { <br /> abstract void open(); <br /> abstract void close()Q?<br /> abstract void alarm(); <br /> } <br /> <br /> <br /> 或?<br /> <br /> interface Door { <br /> void open(); <br /> void close(); <br /> void alarm(); <br /> } <br /> <br /> <br /> 那么h报警功能的AlarmDoor的定义方式如下: <br /> <br /> class AlarmDoor extends Door { <br /> void open() { … } <br /> void close() { … } <br /> void alarm() { … } <br /> } <br /> <br /> <br /> 或?<br /> <br /> class AlarmDoor implements Door ?<br /> void open() { … } <br /> void close() { … } <br /> void alarm() { … } <br /> ?<br /> <br /> q种Ҏ(gu)q反了面向对象设计中的一个核心原则ISPQInterface Segregation PricipleQ,在Door的定义中把Door概念本n固有的行为方法和另外一个概?报警?的行为方法؜在了一赗这样引L(fng)一个问题是那些仅仅依赖于Doorq个概念的模块会因ؓ"报警?q个概念的改变(比如Q修改alarmҎ(gu)的参敎ͼ而改变,反之依然?<br /> <br /> 解决Ҏ(gu)二: <br /> <br /> 既然open、close和alarm属于两个不同的概念,Ҏ(gu)ISP原则应该把它们分别定义在代表q两个概늚抽象cM。定义方式有Q这两个概念都用abstract class方式定义Q两个概念都使用interface方式定义Q一个概念用abstract class方式定义Q另一个概念用interface方式定义?<br /> <br /> 昄Q由于Java语言不支持多重承,所以两个概念都使用abstract class方式定义是不可行的。后面两U方式都是可行的Q但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意囄反映是否正确、合理。我们一一来分析、说明?<br /> <br /> 如果两个概念都用interface方式来定义,那么反映出两个问题Q?、我们可能没有理解清楚问题领域,AlarmDoor在概忉|质上到底是Doorq是报警器?2、如果我们对于问题领域的理解没有问题Q比如:我们通过对于问题领域的分析发现AlarmDoor在概忉|质上和Door是一致的Q那么我们在实现时就没有能够正确的揭C我们的设计意图Q因为在q两个概늚定义上(均用interface方式定义Q反映不Zq含义?<br /> <br /> 如果我们对于问题领域的理解是QAlarmDoor在概忉|质上是DoorQ同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢Q前面已l说q,abstract class在Java语言中表CZU承关p,而承关pd本质上是"is a"关系。所以对于Doorq个概念Q我们应该用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行ؓQ所以报警概念可以通过interface方式定义。如下所C: <br /> <br /> abstract class Door { <br /> abstract void open(); <br /> abstract void close()Q?<br /> } <br /> interface Alarm { <br /> void alarm(); <br /> } <br /> class AlarmDoor extends Door implements Alarm { <br /> void open() { … } <br /> void close() { … } <br /> void alarm() { … } <br /> } <br /> <br /> <br /> q种实现方式基本上能够明的反映出我们对于问题领域的理解Q正的揭示我们的设计意图。其实abstract class表示的是"is a"关系Qinterface表示的是"like a"关系Q大家在选择时可以作Z个依据,当然q是建立在对问题领域的理解上的,比如Q如果我们认为AlarmDoor在概忉|质上是报警器Q同时又hDoor的功能,那么上述的定义方式就要反q来了?<br /> <br /> 转蝲人员-Nicholas<br /> </ca><!-- 导入 在此 参考资?-><!-- end 参考资?-> <img src ="http://www.tkk7.com/obpm/aggbug/337451.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/obpm/" target="_blank">obpm</a> 2010-11-07 13:57 <a href="http://www.tkk7.com/obpm/archive/2010/11/07/337451.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZRBAC的权限设计模?/title><link>http://www.tkk7.com/obpm/archive/2010/09/14/331967.html</link><dc:creator>obpm</dc:creator><author>obpm</author><pubDate>Tue, 14 Sep 2010 05:30:00 GMT</pubDate><guid>http://www.tkk7.com/obpm/archive/2010/09/14/331967.html</guid><wfw:comment>http://www.tkk7.com/obpm/comments/331967.html</wfw:comment><comments>http://www.tkk7.com/obpm/archive/2010/09/14/331967.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/obpm/comments/commentRss/331967.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/obpm/services/trackbacks/331967.html</trackback:ping><description><![CDATA[<p align="center"><strong>权限分析文档</strong> <p>ZRBAC的权限设计模型: <p><strong>1 </strong><strong>RBAC </strong><strong>介绍</strong> <p>RBAC 模型作ؓ目前最为广泛接受的权限模型?<p>NIST QThe National Institute of Standards and TechnologyQ美国国家标准与技术研IQ标准RBAC模型?个部件模型组成,q?个部件模型分别是基本模型RBAC0QCore RBACQ、角色分U模型RBAC1QHierarchal RBACQ、角色限制模型RBAC2QConstraint RBACQ和l一模型RBAC3QCombines RBACQ?sup>[1]</sup>。RBAC0模型如图1所C?<p><img border="0" alt="clip_image001.jpg" src="http://www.tkk7.com/images/blogjava_net/anwenhao/clip_image001.jpg" width="482" height="144"><br>图表 1 RBAC 0 模型 <p>l <strong>RBAC0 </strong><strong>定义了能构成一个RBAC控制pȝ的最的元素集合</strong> <p>在RBAC之中,包含用户users(USERS)、角色roles(ROLES)、目标objects(OBS)、操作operations(OPS)、许可权permissions(PRMS)五个基本数据元素Q权限被赋予角色,而不是用P当一个角色被指定l一个用hQ此用户拥有了该角色所包含的权限。会话sessions是用户与Ȁzȝ角色集合之间的映。RBAC0与传l访问控制的差别在于增加一层间接性带来了灉|性,RBAC1、RBAC2、RBAC3都是先后在RBAC0上的扩展?<p>l <strong>RBAC1 </strong><strong>引入角色间的l承关系</strong> <p>角色间的l承关系可分Z般承关pd受限l承关系。一般承关pM要求角色l承关系是一个绝对偏序关p,允许角色间的多ѝ而受限承关pdq一步要求角色承关pL一个树(wi)l构?<p>l <strong>RBAC2 </strong><strong>模型中添加了责Q分离关系</strong> <p>RBAC2 的约束规定了权限被赋予角色时,或角色被赋予用户?以及当用户在某一时刻ȀzM个角色时所应遵循的强制性规则。责dd括静态责dd动态责dR约束与用户-角色-权限关系一起决定了RBAC2模型中用L(fng)讉K许可?<p>l <strong>RBAC3 </strong><strong>包含了RBAC1和RBAC2</strong> <p>既提供了角色间的l承关系Q又提供了责ddpR?<p>建立角色定义表。定出当前系l中角色?<p>因ؓ有承的问题Q所以角色体现出的是一个树(wi)形结构?<p><img border="0" alt="test.bmp" src="http://www.tkk7.com/images/blogjava_net/anwenhao/%E6%9C%AA%E5%91%BD%E5%90%8D1.bmp" width="603" height="407"> <p><strong>2 </strong><strong>权限设计Q?/strong> <p>配置资源以及资源的操?Q?q里资源可以定义Z个通用的资源模型。提供通用的资源统一接口?<p>数据?ER 图: <p><img border="0" alt="clip_image002.gif" src="http://www.tkk7.com/images/blogjava_net/anwenhao/clip_image002.gif" width="553" height="322"> <p>关系图: <p><img border="0" alt="clip_image003.gif" src="http://www.tkk7.com/images/blogjava_net/anwenhao/clip_image003.gif" width="553" height="419"> <p><img border="0" alt="未命?bmp" src="http://www.tkk7.com/images/blogjava_net/anwenhao/%E6%9C%AA%E5%91%BD%E5%90%8D.bmp" width="603" height="739"> <p><strong>3 </strong><strong>分析Q?/strong> <p>Ҏ(gu)以上的类关系囑֒ER囑֏以看出。整个权限可以抽象ؓ五个对象l成?<p><strong>OrgBean : </strong><strong>用于描述org模型?/strong> <p><strong>Role </strong><strong>Q?用于描述角色?/strong> <p><strong>Permission </strong><strong>Q?用于描述权限?/strong> <p><strong>Resource </strong><strong>Q?用于描述资源?/strong> <p><strong>Operation </strong><strong>Q?用于描述操作?/strong> <p><strong></strong> <p><strong>其中Permission中有Resource , Operation 的聚合,资源和操作组成权限?/strong> <p><strong>Role </strong><strong>?Permission 都有自包含。因计到权限的ѝ?/strong> <p><strong>资源Resource 也可能出C颗树(wi)形结构,那资源也要有自包含?/strong> <p><strong></strong> <p><strong>思想 </strong><strong>:</strong> <p>权限pȝ的核心由以下三部分构成: 1. 创造权限, 2. 分配权限Q?3. 使用权限Q然后,pȝ各部分的主要参与者对照如下: 1. 创造权?-Creator 创造, 2. 分配权限 - Administrator 分配Q?3. 使用权限 - User Q?<p>1. Creator 创?Privilege Q?Creator 在设计和实现pȝ时会划分Q一个子pȝ或称为模块,应该有哪些权限。这里完成的?Privilege 与Resource 的对象声明,q没有真正将 Privilege 与具?Resource 实例联系在一P形成 Operator ?<p>2. Administrator 指定 Privilege ?Resource Instance 的关?。在q一步, 权限真正与资源实例联pd了一P 产生?Operator QPrivilege Instance Q?Administrator 利用 Operator q个基本元素Q来创造他理想中的权限模型。如Q创Ԍ创徏用户l,l用L(fng)分配用户Q将用户l与角色兌{等 ... q些操作都是?Administrator 来完成的?<p>3. User 使用 Administrator 分配l的权限M用各个子pȝ?Administrator 是用P在他的心目中有一个比较适合他管理和l护的权限模型。于是,E序员只要回{一个问题,是什么权限可以访问什么资源,也就是前面说?Operator 。程序员提供 Operator 意味着l系l穿上了盔甲?Administrator 可以按照他的意愿来建立他所希望的权限框?可以自行增加Q删除,理 Resource ?Privilege 之间关系。可以自行设定用?User 和角?Role 的对应关pR?( 如果?Creator 看作?Basic 的发明者, Administrator 是 Basic 的用者,他可以做一些脚本式的编E?) Operator 是这个系l中最关键的部分,它是一个纽带,一个系?Programmer Q?Administrator Q?User 之间的纽带?<p><strong></strong> <p><strong>4 </strong><strong>权限API</strong> <p><strong> getPermissionByOrgGuid(String orgGuid )</strong> <p>通过传入一个org的Guid Q?拿到当前q个org对象都具有那些访问权限?<p><strong> getSourcePermissionByOrgGuid(String orgGuid , String resouceGuid)</strong> <p>通过传入一个org的Guid ?一个资源的Guid Q?q回改Org对当前这个资源的讉K权限?<p><strong>getPermissionByResourceGuid(String resource)</strong> <p>通过传入一个资源的Guid Q?得到当前资源下都有那些权限定义?<p><strong>havingHeritPermission(String orgGuid , String resouceGuid) : Boolean</strong> <p>传入一个orgGuidQ?资源GUID Q查看改OrgGuid下对资源是否有向下承的权限。这里承是资源的ѝ即对父栏目有权限,可以l承下去对父栏目下的子栏目同h权限?<p><strong>havingPermission(String orgGuid , String resourceGuid) : Boolean</strong> <p>判断某OrgҎ(gu)一资源是否用权限?<p>以上是粗_度的权限API ?以下为细_度的权限: <p><strong>getOperationByPermission(String permissionGuid)</strong> <p>通过permission 的Guid 得到该permission 的所有有效操作?<p><strong>getOperationByGuid(String permissionGuid , String resourceGuid)</strong> <p>通过permision的Guid Q?资源的Guid 得到该资源下所有的有效操作?<p><strong>screeningOpreationByGuid (String permissionGuid , String resourceGuid , String orgGuid)</strong> <p>通过permission Q?resource Q?org的Guid 得到改Org对这一资源的有效操作?<p><strong>hasOperation(String operationGuid) : boolean</strong> <p>通过传入的operationGuid q回是否h操作权限?<p><strong>5 </strong><strong>权限的实玎ͼ</strong> <p>1 Q表单式认证Q这是常用的Q但用户到达一个不被授权访问的资源Ӟ Web 容器发 <p>Z?html 面Q要求输入用户名和密码?<p>2 Q用 Filter 防止用户讉K一些未被授权的资源Q?Filter 会截取所?Request/Response Q?<p>然后攄一个验证通过的标识在用户?Session 中,然后 Filter 每次依靠q个标识来决定是否放?Response ?<p>q个模式分ؓQ?<p>Gatekeeper Q采?Filter 或统一 Servlet 的方式?<p>Authenticator Q??Web 中?JAAS 自己来实现?<p>Filter 拦截只是拦截该用h否有讉Kq个面Q或q一资源的权限。真正做到显C后拦截是在应用E序内部d?<p>做显C拦截提供API Q?标签q两U方?<p>  <p>转蝲人员QHappy <p><b>原文地址</b> <a >http://blog.csdn.net/huanghanzzz2006/archive/2006/12/04/1429666.aspx</a> <img src ="http://www.tkk7.com/obpm/aggbug/331967.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/obpm/" target="_blank">obpm</a> 2010-09-14 13:30 <a href="http://www.tkk7.com/obpm/archive/2010/09/14/331967.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LDAP快速入?/title><link>http://www.tkk7.com/obpm/archive/2010/08/28/330195.html</link><dc:creator>obpm</dc:creator><author>obpm</author><pubDate>Sat, 28 Aug 2010 06:38:00 GMT</pubDate><guid>http://www.tkk7.com/obpm/archive/2010/08/28/330195.html</guid><wfw:comment>http://www.tkk7.com/obpm/comments/330195.html</wfw:comment><comments>http://www.tkk7.com/obpm/archive/2010/08/28/330195.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/obpm/comments/commentRss/330195.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/obpm/services/trackbacks/330195.html</trackback:ping><description><![CDATA[<p align="center"><span style="font-size: 36pt"><strong>LDAP</strong><strong>快速入?/strong></span></p> <h1>1. LDAP?/h1> <p>  LDAPQ轻量目录讉K协议QLightweight Directory Access Protocol)是实现提供被UCؓ目录服务的信息服务。目录服务是一U特D的数据库系l,其专门针对读取,览和搜索操作进行了特定的优化。目录一般用来包含描q性的Q基于属性的信息q支持精l复杂的qo能力。目录一般不支持通用数据库针对大量更新操作操作需要的复杂的事务管理或回卷{略。而目录服务的更新则一般都非常单。这U目录可以存储包括个Z息、web铄、jpeg囑փ{各U信息。ؓ了访问存储在目录中的信息Q就需要用运行在TCP/IP 之上的访问协议—LDAP?/p> <p> </p> <p>  LDAP目录中的信息是是按照?wi)型l构l织Q具体信息存储在条目(entry)的数据结构中。条目相当于关系数据库中表的记录Q条目是h区别名DN QDistinguished NameQ的属性(AttributeQ,DN是用来引用条目的QDN相当于关pL据库表中的关键字QPrimary KeyQ。属性由cdQTypeQ和一个或多个|ValuesQ组成,相当于关pL据库中的字段QFieldQ由字段名和数据cdl成Q只是ؓ了方便检索的需要,LDAP中的Type可以有多个ValueQ而不是关pL据库中ؓ降低数据的冗余性要求实现的各个域必L不相关的。LDAP中条目的l织一般按照地理位|和l织关系q行l织Q非常的直观。LDAP把数据存攑֜文g中,为提高效率可以用基于烦引的文g数据库,而不是关pL据库。类型的一个例子就是mailQ其值将是一个电(sh)子邮件地址?/p> <p> </p> <p>LDAP的信息是以树(wi)型结构存储的Q在?wi)根一般定义国?c=CN)或域?dc=com)Q在其下则往往定义一个或多个l织 (organization)(o=Acme)或组l单?organizational units) (ou=People)。一个组l单元可能包含诸如所有雇员、大楼内的所有打印机{信息。此外,LDAP支持Ҏ(gu)目能够和必须支持哪些属性进行控Ӟq是有一个特D的UCؓ对象cd(objectClass)的属性来实现的。该属性的值决定了该条目必遵循的一些规则,其规定了该条目能够及臛_应该包含哪些属性。例如:inetorgPerson对象c需要支持sn(surname)和cn(common name)属性,但也可以包含可选的如邮Ӟ?sh)话L(fng){属性?/p> <p> </p> <h1>2. LDAPU对?/h1> <ol> <li>o– organizationQ组l?公司Q? <li>ou – organization unitQ组l单?部门Q? <li>c - countryNameQ国Ӟ <li>dc - domainComponentQ域名) <li>sn – suer nameQ真实名Uͼ <li>cn - common nameQ常用名Uͼ </li> </ol> <p> </p> <h1>3. 目录设计</h1> <p>设计目录l构是LDAP最重要的方面之一。下面我们将通过一个简单的例子来说明如何设计合理的目录l构。该例子通过Netscape地址薄来访文。假设有一个位于美国US(c=US)而且跨越多个州的名ؓAcme(o=Acme)的公司。Acme希望为所有的雇员实现一个小型的地址薄服务器?</p> <p> </p> <p>  我们从一个简单的l织DN开始: </p> <p>    dn: o=Acme, c=US</p> <p> </p> <p>  Acme所有的l织分类和属性将存储在该DN之下Q这个DN在该存储在该服务器的目录是唯一的。Acme希望其雇员的信息分Zc:理?ou= Managers)和普通雇?ou=Employees),q种分类产生的相对区别名(RDN,relative distinguished names。表C相对于点DN)shi Q?</p> <p> </p> <p>    dn: ou=Managers, o=Acme, c=US</p> <p>    dn: ou=Employees, o=Acme, c=US</p> <p> </p> <p>  在下面我们将会看到分层结构的l成Q顶Ҏ(gu)US的AcmeQ下面是理者组l单元和雇员l织单元。因此包括Managers和Employees的DNl成为: </p> <p>    dn: cn=Jason H. Smith, ou=Managers, o=Acme, c=US</p> <p>    dn: cn=Ray D. Jones, ou=Employees, o=Acme, c=US</p> <p>    dn: cn=Eric S. Woods, ou=Employees, o=Acme, c=US</p> <p> </p> <p>  Z引用Jason H. Smith的通用?common name )条目QLDAP采用cn=Jason H. Smith的RDN。然后将前面的父条目l合在一起就形成如下的树(wi)型结构: </p> <p> </p> <p>    cn=Jason H. Smith</p> <p>        + ou=Managers</p> <p>            + o=Acme</p> <p>                + c=US</p> <p>                               -> dn: cn=Jason H. Smith,ou=Managers,o=Acme,c=US</p> <p> </p> <p> </p> <p>  现在已经定义好了目录l构Q下一步就需要导入目录信息数据。目录信息数据将被存攑֜LDIF文g中,其是导入目录信息数据的默认存放文件。用户可以方便的~写Perl脚本来从例如/etc/passwd、NIS{系l文件中自动创徏LDIF文g?/p> <p> </p> <p>  下面的实例保存目录信息数据ؓtestdate.ldif文gQ该文g的格式说明将可以在man ldif中得到?/p> <p>  在添加Q何组l单元以前,必须首先定义Acme DNQ  </p> <p>    dn: o=Acme, c=US</p> <p>    objectClass: organization</p> <p> </p> <p>  q里o属性是必须?</p> <p>    o: Acme</p> <p> </p> <p>  下面是管理组单元的DNQ在dM理者信息以前,必须先定义该条目?</p> <p>    dn: ou=Managers, o=Acme, c=US</p> <p>    objectClass: organizationalUnit</p> <p>q里ou属性是必须的?</p> <p> </p> <p>ou: Managers</p> <p>  W一个管理者DNQ?</p> <p>    dn: cn=Jason H. Smith, ou=Managers, o=Acme, c=US</p> <p>    objectClass: inetOrgPerson</p> <p>  cn和sn都是必须的属性: </p> <p>    cn: Jason H. Smith</p> <p>    sn: Smith</p> <p>  但是q可以定义一些可选的属性:</p> <p>    telephoneNumber: 111-222-9999</p> <p>    mail: headhauncho@acme.com</p> <p>    localityName: <st1:place><st1:city>Houston</st1:city></st1:place></p> <p> </p> <p>  可以定义另外一个组l单元: </p> <p>    dn: ou=Employees, o=Acme, c=US</p> <p>    objectClass: organizationalUnit</p> <p>    ou: Employees</p> <p> </p> <p>  q添加雇员信息如下: </p> <p>    dn: cn=Ray D. Jones, ou=Employees, o=Acme, c=US</p> <p>    objectClass: inetOrgPerson</p> <p>    cn: Ray D. Jones</p> <p>    sn: Jones</p> <p>    telephoneNumber: 444-555-6767</p> <p>    mail: jonesrd@acme.com</p> <p>    localityName: <st1:place><st1:city>Houston</st1:city></st1:place></p> <p>    dn: cn=Eric S. Woods, ou=Employees, o=Acme, c=US</p> <p>    objectClass: inetOrgPerson</p> <p>    cn: Eric S. Woods</p> <p>    sn: Woods</p> <p>    telephoneNumber: 444-555-6768</p> <p>    mail: woodses@acme.com</p> <p>    localityName: <st1:place><st1:city>Houston</st1:city></st1:place></p> <p><st1:place><st1:city></st1:city></st1:place> </p> <p> </p> <h1>4. 配置OpenLDAP</h1> <p>本文实践了在 Windows 下安装配 openldapQƈd一个条目,LdapBrowser 览Q及 Java E序q接 openldap 的全q程?/p> <p> </p> <p>1. 下蝲安装 <strong>openldap</strong> for windowsQ当前版?st1:chsdate isrocdate="False" islunardate="False" day="30" month="12" year="1899">2.2.29</st1:chsdate>下蝲地址Qhttp://download.bergmans.us/openldap/openldap-<st1:chsdate isrocdate="False" islunardate="False" day="30" month="12" year="1899">2.2.29</st1:chsdate>/openldap-2.2.29-db-4.3.29-openssl-0.<st1:chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="9.8" unitname="a">9.8a</st1:chmetcnv>-win32_Setup.exe</p> <p>    相关链接Qhttp://lucas.bergmans.us/hacks/openldap/</p> <p>   安装很简单,一?next 卛_Q假设我们安装在 c:\openldap</p> <p> </p> <p>2. 配置 openldapQ编?sldap.conf 文g</p> <p>   1) 打开 c:\openldap\sldap.confQ找?/p> <p>    include  C:/openldap/etc/schema/core.schemaQ在它后面添?/p> <p>    include  C:/openldap/etc/schema/cosine.schema</p> <p>    include  C:/openldap/etc/schema/inetorgperson.schema</p> <p> </p> <p>    接下来的例子只需要用C上三?schemaQ当Ӟ如果你觉得需要的话,你可以把其他?schema 全部dq来</p> <p>    include  C:/openldap/etc/schema/corba.schema</p> <p>    include  C:/openldap/etc/schema/dyngroup.schema</p> <p>    include  C:/openldap/etc/schema/java.schema</p> <p>    include  C:/openldap/etc/schema/misc.schema</p> <p>    include  C:/openldap/etc/schema/nis.schema</p> <p>    include  C:/openldap/etc/schema/openldap.schema</p> <p> </p> <p>   2) q是?sldap.conf 文g中,扑ֈ</p> <p>    suffix  "dc=my-domain,dc=com"</p> <p>    rootdn  "cn=Manager,dc=my-domain,dc=com"</p> <p>    把这两行改ؓ</p> <p>    suffix "o=teemlink,c=cn"  </p> <p>    rootdn "cn=Manager,o=teemlink,dc=cn" </p> <p> </p> <p>    suffix 是看自己如何定义了Q后面步骤的 ldif 文g必M它定义了。还要注意到q个配置文g中有一?rootpw  secretQ这?secret ?cn=Manager 的密码,以后会用刎ͼ不过q里是明文密码,你可以用命oQ?slappasswd -h {MD5} -s secret 出加密的密?{MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== 取代配置中的 secret?/p> <p> </p> <p>3. 启动 openldap</p> <p>    CMD q入?c:\openldap 下,q行命o sldapd -d 1</p> <p>    用可以看到控制台下打C片信息,openldap 默认是用?Berkeley DB 数据库存储目录数据的?/p> <p> </p> <p>4. 建立条目,~辑导入 ldif 文g</p> <p>   1) 新徏一?ldif(LDAP Data Interchanged Format) 文g(U文本格?Q例?test.ldifQ文件内容如下:</p> <p>    </p> <p>dn: o=teemlink</p> <p>objectclass: top</p> <p>objectclass: organization</p> <p>o: develop</p> <p> </p> <p>   2) 执行命oQldapadd -l test.ldif</p> <p> </p> <p>5. 使用LDAP Browserq行讉K</p> <p>       5.1安装LDAP Browser2.6软gQ进行如下操作:</p> <p>    <img alt="" src="http://pic002.cnblogs.com/img/obpm/201008/2010082814190153.jpg" /></p> <p>  <img alt="" src="http://pic002.cnblogs.com/img/obpm/201008/2010082814200667.jpg" /></p> <p> </p> <p>5.2昄效果</p> <p>  <img alt="" src="http://pic002.cnblogs.com/img/obpm/201008/2010082814363213.jpg" /></p> <p> </p> <h1>5. Java操作LDAP</h1> <p> </p> <h2>5.1 用JNDIq访?/h2> <div id="eoio4ow" class="cnblogs_code" style="width: 718px; height: 885px"> <pre> <div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">package</span><span style="color: #000000"> cn.myapps.test;<br /> <br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> java.util.Hashtable;<br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.naming.Context;<br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.naming.NamingException;<br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.naming.directory.Attributes;<br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.naming.directory.DirContext;<br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> javax.naming.directory.InitialDirContext;<br /> <br /> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">class</span><span style="color: #000000"> LdapTest {<br /> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> JNDILookup() {<br /> String root </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">o=teemlink,c=cn</span><span style="color: #000000">"</span><span style="color: #000000">;<br /> Hashtable env </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> Hashtable();<br /> env.put(Context.INITIAL_CONTEXT_FACTORY, </span><span style="color: #000000">"</span><span style="color: #000000">com.sun.jndi.ldap.LdapCtxFactory</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> env.put(Context.PROVIDER_URL, </span><span style="color: #000000">"</span><span style="color: #000000">ldap://192.168.0.30/</span><span style="color: #000000">"</span><span style="color: #000000"> </span><span style="color: #000000">+</span><span style="color: #000000"> root);<br /> env.put(Context.SECURITY_AUTHENTICATION, </span><span style="color: #000000">"</span><span style="color: #000000">simple</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> env.put(Context.SECURITY_PRINCIPAL, </span><span style="color: #000000">"</span><span style="color: #000000">cn=Nicholas,ou=develop,o=teemlink,c=cn</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> env.put(Context.SECURITY_CREDENTIALS, </span><span style="color: #000000">"</span><span style="color: #000000">123456</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> DirContext ctx </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">;<br /> <br /> </span><span style="color: #0000ff">try</span><span style="color: #000000"> {<br /> ctx </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> InitialDirContext(env);<br /> Attributes attrs </span><span style="color: #000000">=</span><span style="color: #000000"> ctx.getAttributes(</span><span style="color: #000000">"</span><span style="color: #000000">cn=Nicholas,ou=develop</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">Last Name: </span><span style="color: #000000">"</span><span style="color: #000000"> </span><span style="color: #000000">+</span><span style="color: #000000"> attrs.get(</span><span style="color: #000000">"</span><span style="color: #000000">sn</span><span style="color: #000000">"</span><span style="color: #000000">).get());<br /> System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">认证成功</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (javax.naming.AuthenticationException e) {<br /> e.printStackTrace();<br /> System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">认证p|</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (Exception e) {<br /> System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">认证出错Q?/span><span style="color: #000000">"</span><span style="color: #000000">);<br /> e.printStackTrace();<br /> }<br /> </span><span style="color: #0000ff">if</span><span style="color: #000000"> (ctx </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">) {<br /> </span><span style="color: #0000ff">try</span><span style="color: #000000"> {<br /> ctx.close();<br /> } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (NamingException e) {<br /> </span><span style="color: #008000">//</span><span style="color: #008000"> ignore</span><span style="color: #008000"><br /> </span><span style="color: #000000"> }<br /> }<br /> }<br /> <br /> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">static</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) {<br /> LdapTest LDAPTest </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> LdapTest();<br /> LDAPTest.JNDILookup();<br /> }<br /> }</span></div> </pre> </div> <p> </p> <h2>5.2 用JLDAPq访?/h2> <p>讉K地址Q?a >http://www.openldap.org/jldap/</a> q下载相关lib</p> <p> </p> <div id="s4qok44" class="cnblogs_code"> <pre> <div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">import</span><span style="color: #000000"> com.novell.ldap.</span><span style="color: #000000">*</span><span style="color: #000000">;<br /> <br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> java.io.UnsupportedEncodingException;<br /> <br /> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">class</span><span style="color: #000000"> List<br /> <br /> {<br /> <br /> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">static</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args)<br /> <br /> {<br /> </span><span style="color: #0000ff">int</span><span style="color: #000000"> ldapPort </span><span style="color: #000000">=</span><span style="color: #000000"> LDAPConnection.DEFAULT_PORT;<br /> </span><span style="color: #0000ff">int</span><span style="color: #000000"> searchScope </span><span style="color: #000000">=</span><span style="color: #000000"> LDAPConnection.SCOPE_ONE;<br /> </span><span style="color: #0000ff">int</span><span style="color: #000000"> ldapVersion </span><span style="color: #000000">=</span><span style="color: #000000"> LDAPConnection.LDAP_V3;<br /> </span><span style="color: #0000ff">boolean</span><span style="color: #000000"> attributeOnly </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">false</span><span style="color: #000000">;<br /> String attrs[] </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">;<br /> String ldapHost </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">192.168.0.30</span><span style="color: #000000">"</span><span style="color: #000000">;<br /> String loginDN </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">cn=Manager,o=teemlink,c=cn</span><span style="color: #000000">"</span><span style="color: #000000">;<br /> String password </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">secret</span><span style="color: #000000">"</span><span style="color: #000000">;<br /> String searchBase </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">ou=develop,o=teemlink,c=cn</span><span style="color: #000000">"</span><span style="color: #000000">;<br /> String searchFilter </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">objectClass=*</span><span style="color: #000000">"</span><span style="color: #000000">;<br /> <br /> LDAPConnection lc </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> LDAPConnection();<br /> </span><span style="color: #0000ff">try</span><span style="color: #000000"> {<br /> </span><span style="color: #008000">//</span><span style="color: #008000"> connect to the server</span><span style="color: #008000"><br /> </span><span style="color: #000000"> lc.connect(ldapHost, ldapPort);<br /> <br /> </span><span style="color: #008000">//</span><span style="color: #008000"> bind to the server</span><span style="color: #008000"><br /> </span><span style="color: #000000"> lc.bind(ldapVersion, loginDN, password.getBytes(</span><span style="color: #000000">"</span><span style="color: #000000">UTF8</span><span style="color: #000000">"</span><span style="color: #000000">));<br /> <br /> LDAPSearchResults searchResults </span><span style="color: #000000">=</span><span style="color: #000000"><br /> <br /> lc.search(searchBase, </span><span style="color: #008000">//</span><span style="color: #008000"> container to search</span><span style="color: #008000"><br /> </span><span style="color: #000000"> searchScope, </span><span style="color: #008000">//</span><span style="color: #008000"> search scope</span><span style="color: #008000"><br /> </span><span style="color: #000000"> searchFilter, </span><span style="color: #008000">//</span><span style="color: #008000"> search filter</span><span style="color: #008000"><br /> </span><span style="color: #000000"> attrs, </span><span style="color: #008000">//</span><span style="color: #008000"> "1.1" returns entry name only</span><span style="color: #008000"><br /> </span><span style="color: #000000"> attributeOnly); </span><span style="color: #008000">//</span><span style="color: #008000"> no attributes are returned<br /> <br /> </span><span style="color: #008000">//</span><span style="color: #008000"> print out all the objects</span><span style="color: #008000"><br /> </span><span style="color: #000000"> </span><span style="color: #0000ff">while</span><span style="color: #000000"> (searchResults.hasMore()) {<br /> LDAPEntry nextEntry </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">;<br /> </span><span style="color: #0000ff">try</span><span style="color: #000000"> {<br /> nextEntry </span><span style="color: #000000">=</span><span style="color: #000000"> searchResults.next();<br /> System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">\n</span><span style="color: #000000">"</span><span style="color: #000000"> </span><span style="color: #000000">+</span><span style="color: #000000"> nextEntry.getDN());<br /> System.out.println(nextEntry.getAttributeSet());<br /> } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (LDAPException e) {<br /> System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">Error: </span><span style="color: #000000">"</span><span style="color: #000000"> </span><span style="color: #000000">+</span><span style="color: #000000"> e.toString());<br /> </span><span style="color: #008000">//</span><span style="color: #008000"> Exception is thrown, go for next entry</span><span style="color: #008000"><br /> </span><span style="color: #000000"> </span><span style="color: #0000ff">continue</span><span style="color: #000000">;<br /> }<br /> }<br /> <br /> </span><span style="color: #008000">//</span><span style="color: #008000"> disconnect with the server</span><span style="color: #008000"><br /> </span><span style="color: #000000"> lc.disconnect();<br /> <br /> } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (LDAPException e) {<br /> System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">Error: </span><span style="color: #000000">"</span><span style="color: #000000"> </span><span style="color: #000000">+</span><span style="color: #000000"> e.toString());<br /> } </span><span style="color: #0000ff">catch</span><span style="color: #000000"> (UnsupportedEncodingException e) {<br /> System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">Error: </span><span style="color: #000000">"</span><span style="color: #000000"> </span><span style="color: #000000">+</span><span style="color: #000000"> e.toString());<br /> }<br /> System.exit(</span><span style="color: #000000">0</span><span style="color: #000000">);<br /> }<br /> }</span></div> </pre> </div> <p> </p> <h2>5.3 用JDBC-LDAPq访?/h2> <p>讉K地址Q?a >http://www.openldap.org/jdbcldap/</a> q下载相关lib</p> <p> </p> <div id="kaqo2yi" class="cnblogs_code" style="width: 929px; height: 561px"> <pre> <div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">package</span><span style="color: #000000"> jdbcldap;<br /> <br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> java.sql.Connection;<br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> java.sql.DriverManager;<br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> java.sql.ResultSet;<br /> </span><span style="color: #0000ff">import</span><span style="color: #000000"> java.sql.Statement;<br /> <br /> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">class</span><span style="color: #000000"> JdbcLdap {<br /> <br /> </span><span style="color: #008000">/**</span><span style="color: #008000"><br /> * </span><span style="color: #808080">@param</span><span style="color: #008000"> args<br /> * </span><span style="color: #808080">@throws</span><span style="color: #008000"> Exception <br /> </span><span style="color: #008000">*/</span><span style="color: #000000"><br /> </span><span style="color: #0000ff">public</span><span style="color: #000000"> </span><span style="color: #0000ff">static</span><span style="color: #000000"> </span><span style="color: #0000ff">void</span><span style="color: #000000"> main(String[] args) </span><span style="color: #0000ff">throws</span><span style="color: #000000"> Exception {<br /> Class.forName(</span><span style="color: #000000">"</span><span style="color: #000000">com.octetstring.jdbcLdap.sql.JdbcLdapDriver</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> String ldapConnectString </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">jdbc:ldap://192.168.0.30/o=teemlink,c=cn?SEARCH_SCOPE:=subTreeScope</span><span style="color: #000000">"</span><span style="color: #000000">;<br /> Connection con </span><span style="color: #000000">=</span><span style="color: #000000"> DriverManager.getConnection(ldapConnectString, </span><span style="color: #000000">"</span><span style="color: #000000">cn=Manager,o=teemlink,c=cn</span><span style="color: #000000">"</span><span style="color: #000000">, </span><span style="color: #000000">"</span><span style="color: #000000">secret</span><span style="color: #000000">"</span><span style="color: #000000">);<br /> <br /> String sql </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">SELECT * FROM ou=develop,o=teemlink,c=cn</span><span style="color: #000000">"</span><span style="color: #000000">;<br /> <br /> Statement sat </span><span style="color: #000000">=</span><span style="color: #000000"> con.createStatement();<br /> ResultSet rs </span><span style="color: #000000">=</span><span style="color: #000000"> sta.executeQuery(sql);<br /> </span><span style="color: #0000ff">while</span><span style="color: #000000"> (rs.next()) {<br /> System.out.println(rs.getString(</span><span style="color: #000000">1</span><span style="color: #000000">));<br /> }<br /> <br /> </span><span style="color: #0000ff">if</span><span style="color: #000000"> (con </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">)<br /> con.close();<br /> }<br /> }</span></div> </pre> </div> <p> </p> <p>原创人员QNicholas</p> <p> </p> <p> </p> <br /> 文章来源:<a >http://www.cnblogs.com/obpm/archive/2010/08/28/1811065.html</a> <img src ="http://www.tkk7.com/obpm/aggbug/330195.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/obpm/" target="_blank">obpm</a> 2010-08-28 14:38 <a href="http://www.tkk7.com/obpm/archive/2010/08/28/330195.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重构实战案例一Q以子类取代cd~码(原创)http://www.tkk7.com/obpm/archive/2010/07/13/330196.htmlobpmobpmTue, 13 Jul 2010 15:22:00 GMThttp://www.tkk7.com/obpm/archive/2010/07/13/330196.htmlhttp://www.tkk7.com/obpm/comments/330196.htmlhttp://www.tkk7.com/obpm/archive/2010/07/13/330196.html#Feedback0http://www.tkk7.com/obpm/comments/commentRss/330196.htmlhttp://www.tkk7.com/obpm/services/trackbacks/330196.html以子cd代类型编?/span>

 Replace Type Code with Subclasses

1. 何谓重构

 

1.1名词解释

  对Y件内部结构的㆒种调整Q目的是在不改变「Y件之可察行ؓ」前提下Q提高其可理解性,降低其修Ҏ(gu)本?/span>

  

1.2动词解释

  使用一pd重构准则Q手法)Q在不改变「Y件之可察行ؓ」前提下Q调整其l构?/span>

 

2. Z重构

 

2.1「重构」改qY件设?/h2>

  同样完成一件事Q设计不良的E序往往需要更多代码,q常常是因ؓ代码在不同的?/b>方用完全相同的语句做同L(fng)?/b>。因此改q设计的一个重要方向就是消除重复代?b>QDuplicate CodeQ?/span>

 

2.2「重构」软g更易被理?/h2>

  你的源码q有其它读者:C月之后可能会有另一位程序员试L你的代码q做一些修?/b>。我们很Ҏ(gu)忘记q第二位读者,但他才是最重要的。计器是否多花了数个钟头进行编译,又有什么关pdQ如果一个程序员p一周时间来修改某段代码Q那才关p重?mdash; 如果他理解你的代码,q个修改原本只需一时

 

2.3「重构」助你找到臭?Q?bugsQ?/h2>

  Kent Beck l常形容自己的㆒句话Q?b>我不是个伟大的程序员Q我只是个有着?/b>些优U?fn)惯的好E序员而已。』重构能够帮助我更有效地写出强固E_QrobustQ的代码?b> 

 

2.4「重构」助你提高编E速度

  l于Q前面的一切都归结Cq最后一点:重构帮助你更快速地开发程序。听h有违反直觉。当我谈到重构,Z很容易看出它能够提高质量?b>改善设计、提升可L、减错?/b>Q这些都是提高质量。但q难道不会降低开发速度吗?我强烈相信:良好设计是快速Y件开发的Ҏ(gu)。事实上拥有良好设计才可能达成快速的开发?b>如果没有良好设计Q或许某D|间内你的q展q速,但恶劣的设计很快p你的速度?/b>?/b>来。你会把旉花在调试?/b>面,无法d新功?/b>。修Ҏ(gu)间愈来愈长,因ؓ你必花愈来愈多的时间去理解pȝ、寻N复代码。随着你给最初程序打上一个又一个的补丁QpatchQ,新特性需要更多代码才能实现。真是个恶性@环?

 

3.何时重构Q?/h1>

  重构本来׃是一件「特别拨出时间做」的事情Q重构应该随旉地进?/span>。你不应该ؓ重构而重构,你之所以重构,是因Z惛_别的什么事Q而重构可以帮助你把那些事做好

 

3.1三次法则QThe Rule of ThreeQ?/h2>

  Don Roberts l了我一条准则:W一ơ做某g事时只管dQ第二次做类似的事会产生反感Q但无论如何q是做了Q第三次再做cM的事Q你应该重构?

  ?nbsp;事不q?/b>?/b>Q?/b>?/b>则重构。(Three strikes and you refactor.Q?/b>

 

3.2重构时机

  d功能时一q?/span>

  修补错误时一q?/span>

  复审代码时一q?

 

-以上章节摘抄自《重?改善既有代码的设?b>?/b>

 

4.q_重构案例

 

4.1重构动机

  1. 实例模块为ViewQ重构元素ؓViewAction、ViewProcessBean、ViewQ以下ؓ关系图?/span>

  

  2. ׃View存在多种editModeQ编辑模式)Q而每个调用的地方都需要进行type codeQ类型码Q判?/b>Q然后再q行相应的业务逻辑处理Q最l在每个调用的地斚w形成了大量的if-else代码Q大大减׃代码的可L,和逻辑清晰度?/span>

 

  3. 调用的地方:

  

4.2重构作法

  

 

如上图所C,每Utype code重构成subclassQ加Z每种cd处理业务逻辑的能力?/span>

 

View-版本1566代码片段Q?/span>

 

public EditMode getEditModeType() {
if (EDIT_MODE_CODE_DQL.equals(getEditMode())) {
return new DQLEditMode(this);
}
else if (EDIT_MODE_CODE_SQL.equals(getEditMode())) {
return new SQLEditMode(this);
}
else if (EDIT_MODE_DESIGN.equals(getEditMode())) {
return new DesignEditMode(this);
}

return new NullEditMode(this);
}

说明Q调用者无需了解具体的类型,由View自n作判断,q回EditMode接口Q从而实现多态调用?/span>

 

 

ViewProcessBean代码片段Q?/span>

重构?版本1503Q?/span>

 

public String expDocToExcel(String viewid, WebUser user, ParamsTable params) throws Exception {
if (view.getEditMode().equals(View.EDIT_MODE_DESIGN)) {
datas
= dp.queryBySQLPage(sql, params, tempPage, LINES, user.getDomainid());
}
else if (view.getEditMode().equals(View.EDIT_MODE_CODE_DQL)) {
datas
= dp.queryByDQLPage(dql, params, tempPage, LINES, user.getDomainid());
}
else if (view.getEditMode().endsWith(View.EDIT_MODE_CODE_SQL)) {
datas
= dp.queryBySQLPage(sql, params, tempPage, LINES, user.getDomainid());
}
}

 

重构?版本1566Q?/span>

 

public String expDocToExcel(String viewid, WebUser user, ParamsTable params) throws Exception {
datas
= view.getEditModeType().getDataPackage(params, tempPage, LINES, user, currdoc);
//其他业务逻辑
}

 

 

5.l语

  ׃q案例可看到Q引入subclass代替type code可以大大减少if-else判断Q而且可以把责d聚到每种type中,使代码结构更清晰易懂?/span>

 

6.其他

       在本案例中引入了I类型概念,?/span>NullEditModeQ代码如下:

  

/**
*
*
@author nicholas zhen
*
*/
public class NullEditMode extends AbstractEditMode implements EditMode {

public NullEditMode(View view) {
super(view);
}

public String getQueryString(ParamsTable params, WebUser user, Document sDoc) {
return "";
}

public DataPackage getDataPackage(ParamsTable params, WebUser user, Document doc) throws Exception {
return new DataPackage();
}

public DataPackage getDataPackage(ParamsTable params, int page, int lines, WebUser user, Document doc) throws Exception {
return new DataPackage();
}

public long count(ParamsTable params, WebUser user, Document doc) throws Exception {
return 0;
}
}

说明Q空cd保证了调用每个方法都有默认D回,而不需要进行非I判断,当View没有cdӞ卌回默认的I类?/span>

 

原创人员QNicholas


文章来源:http://www.cnblogs.com/obpm/archive/2010/07/13/1776856.html

obpm 2010-07-13 23:22 发表评论
]]>Hibernate的乐观锁与?zhn)观?转蝲)http://www.tkk7.com/obpm/archive/2010/07/11/330200.htmlobpmobpmSun, 11 Jul 2010 01:58:00 GMThttp://www.tkk7.com/obpm/archive/2010/07/11/330200.htmlhttp://www.tkk7.com/obpm/comments/330200.htmlhttp://www.tkk7.com/obpm/archive/2010/07/11/330200.html#Feedback0http://www.tkk7.com/obpm/comments/commentRss/330200.htmlhttp://www.tkk7.com/obpm/services/trackbacks/330200.html锁( locking Q?
业务逻辑的实现过E中Q往往需要保证数据访问的排他性。如在金融系l的日终l算处理中,我们希望针对某个 cut-off 旉点的数据q行处理Q而不希望在结进行过E中Q可能是几秒U,也可能是几个时Q,数据再发生变化。此Ӟ我们需要通过一些机制来保证q些数据在某个操作过E中不会被外界修改,q样的机Ӟ在这里,也就是所谓的 “?rdquo; Q即l我们选定的目标数据上锁,使其无法被其他程序修攏VHibernate 支持两种锁机Ӟ即通常所说的 “(zhn)观锁( Pessimistic Locking Q?rdquo;?“乐观锁( Optimistic Locking Q?rdquo; ?br />
(zhn)观锁( Pessimistic Locking Q?
(zhn)观锁,正如其名Q它指的是对数据被外界(包括本系l当前的其他事务Q以及来自外部系l的事务处理Q修Ҏ(gu)保守态度Q因此,在整个数据处理过E中Q将数据处于锁定状态。?zhn)观锁的实玎ͼ往往依靠数据库提供的锁机Ӟ也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则Q即使在本系l中实现了加锁机Ӟ也无法保证外部系l不会修Ҏ(gu)据)?
一个典型的倚赖数据库的(zhn)观锁调用:
select * from account where name=”Erica” for update
q条 sql 语句锁定?account 表中所有符合检索条Ӟname=”Erica”Q的记录。本ơ事务提交之前(事务提交时会释放事务q程中的锁)Q外界无法修改这些记录。Hibernate 的?zhn)观锁Q也是基于数据库的锁机制实现?br />下面的代码实CҎ(gu)询记录的加锁Q?
String hqlStr ="from TUser as user where user.name='Erica'";
Query query = session.createQuery(hqlStr);
query.setLockMode("user",LockMode.UPGRADE); // 加锁
List userList = query.list();// 执行查询Q获取数?/span>

query.setLockMode Ҏ(gu)询语句中Q特定别名所对应的记录进行加锁(我们为TUser cL定了一个别?“user” Q,q里也就是对q回的所?user 记录q行加锁?br />观察q行?Hibernate 生成?SQL 语句Q?br />select tuser0_.id as id, tuser0_.name as name, tuser0_.group_id
as group_id, tuser0_.user_type as user_type, tuser0_.sex as sex
from t_user tuser0_ where (tuser0_.name='Erica' ) for update

q里 Hibernate 通过使用数据库的 for update 子句实现了?zhn)观锁机制?
Hibernate 的加锁模式有Q?
LockMode.NONE Q?/strong> 无锁机制?
LockMode.WRITE Q?/strong> Hibernate ?Insert ?Update 记录的时候会自动获取?
LockMode.READ Q?/strong> Hibernate 在读取记录的时候会自动获取?br />以上q三U锁机制一般由 Hibernate 内部使用Q如 Hibernate Z保证 Updateq程中对象不会被外界修改Q会?save Ҏ(gu)实现中自动ؓ目标对象加上 WRITE 锁?br />LockMode.UPGRADE Q?/strong>利用数据库的 for update 子句加锁?
LockMode. UPGRADE_NOWAIT Q?/strong> Oracle 的特定实玎ͼ利用 Oracle ?for update nowait 子句实现加锁?
上面q两U锁机制是我们在应用层较为常用的Q加锁一般通过以下Ҏ(gu)实现Q?
Criteria.setLockMode
Query.setLockMode
Session.lock

注意Q只有在查询开始之前(也就?Hiberate 生成 SQL 之前Q设定加锁,才会真正通过数据库的锁机制进行加锁处理,否则Q数据已l通过不包?for update 子句?Select SQL 加蝲q来Q所谓数据库加锁也就无从谈v?br />
乐观锁( Optimistic Locking Q?
相对(zhn)观锁而言Q乐观锁机制采取了更加宽杄加锁机制。?zhn)观锁大多数情况下依靠数据库的锁机制实玎ͼ以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销Q特别是寚w事务而言Q这L(fng)开销往往无法承受?
如一个金融系l,当某个操作员d用户的数据,q在d的用h据的基础上进行修Ҏ(gu)如更改用户帐户余额)Q如果采用?zhn)观锁机制Q也意味着整个操作q程中(从操作员d数、开始修改直x交修改结果的全过E,甚至q包括操作员中途去煮咖啡的旉Q,数据库记录始l处于加锁状态,可以惌Q如果面对几百上千个q发Q这L(fng)情况导致怎样的后果。乐观锁机制在一定程度上解决了这个问题。乐观锁Q大多是Z数据版本Q?Version Q记录机制实现。何谓数据版本?即ؓ数据增加一个版本标识,在基于数据库表的版本解决Ҏ(gu)中,一般是通过为数据库表增加一?“version” 字段来实现?
d出数据时Q将此版本号一同读出,之后更新ӞҎ(gu)版本号加一。此Ӟ提交数据的版本数据与数据库表对应记录的当前版本信息q行比对Q如果提交的数据版本号大于数据库表当前版本号Q则予以更新Q否则认为是q期数据?
对于上面修改用户帐户信息的例子而言Q假设数据库中帐户信息表中有一个version 字段Q当前gؓ 1 Q而当前帐户余额字D(balanceQؓ $100 ?
1 操作?A 此时其dQversion=1Q,q从其帐户余额中扣除 $50Q?100-$50Q?
2 在操作员 A 操作的过E中Q操作员 B 也读入此用户信息Qversion=1Q,q从其帐户余额中扣除 $20 Q?100-$20Q?
3 操作?A 完成了修改工作,数据版本号加一Qversion=2Q,q同帐户扣除后余额(balance=$50Q,提交x据库更新Q此时由于提交数据版本大于数据库记录当前版本Q数据被更新Q数据库记录 version 更新?2 ?
4 操作?B 完成了操作,也将版本号加一Qversion=2Q试囑֐数据库提交数据(balance=$80Q,但此时比Ҏ(gu)据库记录版本时发玎ͼ操作?B 提交的数据版本号?2 Q数据库记录当前版本也ؓ 2 Q不满“ 提交版本必须大于记录当前版本才能执行更新“ 的乐观锁{略Q因此,操作?B 的提交被驛_。这P避免了操作?B 用基?version=1 的旧数据修改的结果覆盖操作员 A 的操作结果的可能?
从上面的例子可以看出Q乐观锁机制避免了长事务中的数据库加锁开销Q操作员 A 和操作员 B 操作q程中,都没有对数据库数据加锁)Q大大提升了大ƈ发量下的pȝ整体性能表现。需要注意的是,乐观锁机制往往Zpȝ中的数据存储逻辑Q因此也具备一定的局限性,如在上例中,׃乐观锁机制是在我们的pȝ中实玎ͼ来自外部pȝ的用户余额更新操作不受我们系l的控制Q因此可能会造成脏数据被更新到数据库中。在pȝ设计阶段Q我们应该充分考虑到这些情况出现的可能性,q进行相应调_如将乐观锁策略在数据库存储过E中实现Q对外只开攑֟于此存储q程的数据更新途径Q而不是将数据库表直接对外公开Q?
Hibernate 在其数据讉K引擎中内|了乐观锁实现。如果不用考虑外部pȝҎ(gu)据库的更新操作,利用 Hibernate 提供的透明化乐观锁实现Q将大大提升我们的生产力?
Hibernate 中可以通过 class 描述W的 optimistic-lock 属性结?version描述W指定?br />
现在Q我们ؓ之前CZ中的 TUser 加上乐观锁机制?br />1 Q?首先?TUser ?class 描述W添?optimistic-lock 属性:
<hibernate-mapping>
<class name="org.hibernate.sample.TUser" table="t_user" dynamic-update="true"
dynamic-insert="true" optimistic-lock="version">
……
</class>
</hibernate-mapping>

optimistic-lock 属性有如下可选取| 
noneQ?/strong>无乐观锁 
versionQ?/strong>通过版本机制实现乐观?
dirtyQ?/strong>通过查发生变动过的属性实C观锁
allQ?/strong>通过查所有属性实C观锁
其中通过 version 实现的乐观锁机制?Hibernate 官方推荐的乐观锁实现Q同时也?Hibernate 中,目前唯一在数据对象脱?Session 发生修改的情况下依然有效的锁机制。因此,一般情况下Q我们都选择 version 方式作ؓ Hibernate 乐观锁实现机制?
2 Q?d一?Version 属性描q符
<hibernate-mapping>
<class name="org.hibernate.sample.TUser" table="t_user" dynamic-update="true" dynamic-insert="true"
optimistic-lock="version">
<id name="id" column="id" type="java.lang.Integer">
<generator class="native">
</generator>
</id>
<version column="version" name="version" type="java.lang.Integer"/>
……
</class>
</hibernate-mapping>

注意 version 节点必须出现?ID 节点之后。这里我们声明了一?version 属性,用于存放用户的版本信息,保存?TUser 表的version 字段中?
此时如果我们试~写一D代码,更新 TUser 表中记录数据Q如Q?
Criteria criteria = session.createCriteria(TUser.class);
criteria.add(Expression.eq("name","Erica"));
List userList = criteria.list();
TUser user =(TUser)userList.get(0);
Transaction tx = session.beginTransaction();
user.setUserType(1); // 更新 UserType 字段
tx.commit();

每次?TUser q行更新的时候,我们可以发现Q数据库中的 version 都在递增。而如果我们尝试在 tx.commit 之前Q启动另外一?Session Q对名ؓ Erica 的用戯行操作,以模拟ƈ发更新时的情形:
Session session= getSession();
Criteria criteria = session.createCriteria(TUser.class);
criteria.add(Expression.eq("name","Erica"));
Session session2 = getSession();
Criteria criteria2 = session2.createCriteria(TUser.class);
criteria2.add(Expression.eq("name","Erica"));
List userList = criteria.list();
List userList2 = criteria2.list();TUser user =(TUser)userList.get(0);
TUser user2 =(TUser)userList2.get(0);
Transaction tx = session.beginTransaction();
Transaction tx2 = session2.beginTransaction();
user2.setUserType(99);
tx2.commit();
user.setUserType(1);
tx.commit();
执行以上代码Q代码将?tx.commit() 处抛?StaleObjectStateException 异常Qƈ指出版本查失败,当前事务正在试图提交一个过期数据。通过捕捉q个异常Q我们就可以在乐观锁校验p|时进行相应处理?/p>

 

转蝲人员QNicholas


文章来源:http://www.cnblogs.com/obpm/archive/2010/07/11/1775120.html

obpm 2010-07-11 09:58 发表评论
]]>
վ֩ģ壺 ˳վɫ߹ۿ| ޸ŮBBW| Ůѹۿվh| ˳վɫ߹ۿ| ޾Ʒھþ| 99re6߾ƷƵѲ| a뾫Ʒɫҹ| þþ޾Ʒ| Ʒþþþþþ| 㶮õ߹ۿƵ| ɫվWWWĻ| ޾Ʒ| պƵ| ԴWWW| mvƷmvձmv| ˾޾ƷӰwww| 99ƵƷѹۿ7| վ| ۺϾƷ˾þ| AVպAVһ| պѲ| ƷѾþþþþþ| ž99°| ޾Ʒ޲߲| ˳ַ߹ۿ | 2021Ƶ| jŮpƵ| ۺavһ| AVþüįٸ| һëƬڼ| Ůվ߿| ĻѸƵ| ƷѴƬһ| ޾Һ| ɫһ| ޳aƬ߹ۿ| ҹAVר߲| պƷƬҹѹ| ѹվ߹ۿ| ŮˬˬˬƵ| Ůѹۿվ|