Liferay代码分析与扩展——用户服务

<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8"> <meta name="GENERATOR" content="OpenOffice.org 2.4 (Linux)"> <style type="text/css"> <!-- @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in; background: transparent } P.cjk { font-size: 10pt } H2 { margin-bottom: 0.08in } H2.western { font-family: "Nimbus Sans L", sans-serif; font-size: 14pt; font-style: italic } H2.cjk { font-size: 14pt; font-style: italic } H2.ctl { font-size: 14pt; font-style: italic } H3 { margin-bottom: 0.08in } H3.western { font-family: "Nimbus Sans L", sans-serif } H4 { margin-bottom: 0.08in } H4.western { font-family: "Nimbus Sans L", sans-serif; font-size: 11pt; font-style: italic } H4.cjk { font-size: 11pt; font-style: italic } H4.ctl { font-size: 11pt; font-style: italic } H5 { margin-bottom: 0.08in } H5.western { font-family: "Nimbus Sans L", sans-serif; font-size: 11pt } H5.cjk { font-size: 11pt } H5.ctl { font-size: 11pt } --> </style>

Liferay代码分析与扩展——用户服务

转载请保留作者信息:

作者:88250

Blog:http:/blog.csdn.net/DL88250

MSN & Gmail & QQ:[email protected]

目录

摘要 1

环境 1

导入工程 1

用户服务分析 3

用户服务扩展 3

问题描述 4

解决方案分析 4

Solution 1 4

Solution 2 4

最终方案 4

步骤 4

总结 8



摘要

看了几天Liferay了,由于要和其他系统进行整合,所以分析了一下Liferay的用户服务代码。从其用户服务代码可以看出一些Liferay的主要设计思想,为将来分析他的架构设计做下准备。

环境



导入工程

Liferay5.1.1是用NetBeans建立的Ant工程,源代码包解压后可以在NetBeans中直接打开。其工程视图如下:


Liferay代码分析与扩展——用户服务_第1张图片


先简要介绍一下源代码目录(不包含test目录)。
  • portal-impl

    包含了所有的服务实现代码,例如基本的用户管理、邮件服务、内容管理(CMS,JSR170)

  • portal-service

    包含了portal-impl的所有服务接口

  • portal-kernel

    包含了Portal/Portlet规范实现(JSR 168/268),以及基本的框架管理(Struts、Spring), 还有部署、配置、搜索、WebService、持久化的基本实现

  • support-glassfish/tomcat

    对gsf/tomcat容器的支持实现

  • util-bridges

    对一些框架/语言编写Portlet的支持。当前我们可以使用如下语言/框架来编写Portlet:

  1. Bean Scripting Framework (BSF)

  2. Groovy

  3. Javascript

  4. JSF

  5. JSP

  6. PHP

  7. Python

  8. Ruby

  9. Struts

  10. Web Accessibility Initiative (WAI)

  • util-java/taglib

    Liferay使用的基本Utilities以及标签库实现

用户服务分析

目前,Liferay项目是用Struts1.2.x + Spring 2.0作为基本框架编写的。其架构设计思路清晰明了,是难得的学习设计的示例。下面,进入本文的主题——用户服务分析。

在目录portal-service下展开源包com.liferay.portal.service,可以看到一系列****Service的接口。我们找出与用户相关的,可以得出如下类依赖关系图:

Liferay代码分析与扩展——用户服务_第2张图片


从最上层的两个接口看来,Liferay在用户服务设计方面与EJB3.x的思路是一致的,分为了Local接口与Remote接口,从代码的注释也可以得到这一点。在liferay的当前版本中(5.1.1),在图右边的Remote接口中都将服务适当处理后委托给了图左边的Local实现。其他关键的地方请参考图中的说明部分。



用户服务扩展

这里与其说是“扩展”,不如说是“修改”。

在门户与其他系统进行整合的时候,第一个困难的问题就是用户管理的问题。这里说的用户管理可以简单分为两类管理:身份认证、帐号管理。关于身份认证的问题可以使用CAS(Central Authentication Service)来实现与可系统之间的SSO(Single Sign-On/Out),可以参考这里、还有这里。帐号管理就是当前最头疼的,具体问题描述如下:

问题描述

举个例子:如果Admin在门户Liferay中建立了一个帐号,其余系统也应该建立用户帐号;如果用户在门户中修改了密码,该用户在其余系统中的帐号密码也应该作相应修改,相反则不成立。

解决方案分析

结合先前的用户服务分析类关系图,可以得出如下两个方案:

Solution 1

继承UserLocalServiceImpl类,添加我们需要的功能。

优点:以后Liferay更新了代码,对我们需要的功能不会造成影响,基本不存在代码合并的代价。

缺点:要修改Spring的配置文件,将对UserLocalServiceImpl Bean的引用改为我们的实现Bean配置。

Solution 2

直接修改UserLocalServiceImpl类代码,将所需功能委托给我们的实现。

优点:不需要修改Spring配置文件。

缺点:以后Liferay更新了代码,有一定的代码合并代价。

最终方案

综上,权衡下来。我觉得使用Solution 2。因为我认为目前修改代码对以后升级的合并代价小于修改配置文件的代价。所以,与其说是“扩展”,不如说是“修改” : )



步骤

以添加用户为例:

打开com.liferay.portal.service.impl.UserLocalServiceImpl类,找到addUser方法,在此方法最后加入我们的实现委托:

  1. //unusingspringDI,now,justforsimple.
  2. //by88250,Aug29,2008
  3. newSubsystemUserServiceImpl().registerUser(firstName,lastName,
  4. emailAddress,screenName,password1);

这里没有使用Spring的DI,只是为了简便一点,不用修改配置文件。以后可能会使用Spring DI。

下面就是我们所需服务的实现:

  1. /*
  2. *Tochangethistemplate,chooseTools|Templates
  3. *andopenthetemplateintheeditor.
  4. */
  5. packagecom.jinfonet.developer.portal.service.impl;
  6. importcom.liferay.portal.PortalException;
  7. importcom.liferay.portal.security.pwd.PwdEncryptor;
  8. importjava.io.IOException;
  9. importjava.sql.Connection;
  10. importjava.sql.DriverManager;
  11. importjava.sql.ResultSet;
  12. importjava.sql.SQLException;
  13. importjava.sql.Statement;
  14. importjava.util.logging.Level;
  15. importjava.util.logging.Logger;
  16. importorg.apache.commons.httpclient.HttpClient;
  17. importorg.apache.commons.httpclient.HttpException;
  18. importorg.apache.commons.httpclient.NameValuePair;
  19. importorg.apache.commons.httpclient.methods.PostMethod;
  20. importorg.apache.commons.logging.Log;
  21. importorg.apache.commons.logging.LogFactory;
  22. /**
  23. *Subsystemuserserviceutility.Currently,thisclassismainlyfor
  24. *updatecoherenceofuseraccountsexistedinsomesubsystems(scarab,svn,
  25. *etc.).
  26. *@author88250<[email protected]>
  27. *@version1.0.0.2,Sep2,2008
  28. */
  29. publicclassSubsystemUserServiceImpl{
  30. //TODOplacesallpropertiesinaconfigurationfile,nohard-coding
  31. privatefinalStringdriver="com.mysql.jdbc.Driver";
  32. privatefinalStringdbURL="jdbc:mysql://192.168.128.122:3306/scarab";
  33. privatefinalStringdbUserName="root";
  34. privatefinalStringdbUserPwd="sa";
  35. privateConnectioncon=null;
  36. privatestaticLoglog=LogFactory.getLog(SubsystemUserServiceImpl.class);
  37. privatefinalStringREGISTER_URL="http://daniel-desktop:9090/scarab/issues/template/AutoRegister";
  38. /**
  39. *Defaultconstructor.
  40. *@throwscom.liferay.portal.PortalException
  41. */
  42. publicSubsystemUserServiceImpl()throwsPortalException{
  43. try{
  44. Class.forName(driver);
  45. }catch(ClassNotFoundExceptionex){
  46. log.error(ex);
  47. thrownewPortalException(ex);
  48. }
  49. }
  50. /**
  51. *Changesuser'spasswordinallsubsystems.
  52. *@paramuserNameusername
  53. *@paramnewPwdthenewpassword(cleartext)
  54. *@throwsPortalException
  55. */
  56. publicvoidchangePassword(StringuserName,StringnewPwd)throwsPortalException{
  57. updatePassword(userName,newPwd);
  58. }
  59. /**
  60. *Registersanewuserinallsubsystems.
  61. *@paramfirstNamefirstname
  62. *@paramlastNamelastname
  63. *@paramemailAddressemailadress
  64. *@paramscreenNameusername
  65. *@parampassworduserpassword
  66. *@throwsPortalException
  67. */
  68. publicvoidregisterUser(StringfirstName,StringlastName,StringemailAddress,
  69. StringscreenName,Stringpassword)throwsPortalException{
  70. addUser(firstName,lastName,emailAddress,screenName,password);
  71. }
  72. privatevoidaddUser(StringfirstName,StringlastName,StringemailAddress,
  73. StringscreenName,Stringpassword)throwsPortalException{
  74. HttpClienthttpClient=newHttpClient();
  75. PostMethodregisterMethod=newPostMethod(REGISTER_URL);
  76. NameValuePair[]data={
  77. newNameValuePair("firstName",firstName),
  78. newNameValuePair("lastName",lastName),
  79. newNameValuePair("email",emailAddress),
  80. newNameValuePair("userName",screenName),
  81. newNameValuePair("password",password),
  82. };
  83. registerMethod.setRequestBody(data);
  84. try{
  85. intstatus=httpClient.executeMethod(registerMethod);
  86. log.info("AutoregisterforsubsystemScarabsuccessfully!");
  87. }catch(IOExceptionex){
  88. Logger.getLogger(SubsystemUserServiceImpl.class.getName()).log(Level.SEVERE,null,ex);
  89. log.error("AutoregisterforsubsystemScarabfaild!",ex);
  90. registerMethod.releaseConnection();
  91. }
  92. }
  93. privatevoidupdatePassword(StringuserName,StringnewPwd)throwsPortalException{
  94. StringnewPwdCipherText=PwdEncryptor.encrypt(newPwd);//SHAcryptalgorithm
  95. try{
  96. con=DriverManager.getConnection(dbURL,dbUserName,dbUserPwd);
  97. Statementsmt=con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
  98. ResultSet.CONCUR_UPDATABLE);
  99. smt.executeUpdate("UPDATETURBINE_USERSETPASSWORD_VALUE='"+newPwdCipherText+
  100. "'WHERELOGIN_NAME='"+userName+"'");
  101. smt.close();
  102. con.close();
  103. }catch(SQLExceptionex){
  104. log.error("ScarabDatabasemodifyfailed:",ex);
  105. thrownewPortalException(ex);
  106. }
  107. }
  108. }

总结

Liferay是一个设计很优秀的Portal,他有很多设计思路、代码实现是我们值得学习、借鉴的地方。关于用户服务这一块我们就分析到此,在后续的篇章中我将给大家带来更精彩的Liferay代码分析,定制出适合我们自己的门户系统!请大家继续关注我的Blog哦:http://blog.csdn.net/DL88250

: )



你可能感兴趣的:(liferay)