- burnholy
- 等级: 初级会员
- 性别:
- 文章: 1
- 积分: 30
- 来自: 北京
|
搭建开发环境 安装 jdk1.4.2,jikes1.22,ant1.6.5 以安装在c盘为例 设置环境变量: ANT_HOME =C:\apache-ant-1.6.5 JAVA_HOME =C:\jdk1.5 JIKES_HOME=C:\jikes1.22 设置path变量,增加下面信息 %ANT_HOME%\bin;%JAVA_HOME%\bin;%JIKES_HOME%\bin; 部分情况,classpath变量会干扰环境,可以删除。但我机器上没删除classpath都可以正常运作。 设置完环境变量后,最好重新启动机器,保证设置生效。 安装 Myeclipse并建立portal工程 准备好myecipse软件、iferay-portal-src-4.1.0.zip (1)安装myeclipse。 (2)在e盘建立E:\cmproject目录,将liferay-portal-src-4.1.0.zip解压到e:\cmproject\portal目录下, (3)进入myeclipse,设置file-->switchworkspace 输入E:\cmproject,ok确认 (4)File -->New-->project-->java project 输入项目名称为portal,其他默认,finish结束 如果一切顺利,则在myeclipse左侧边Navigator上看到portal的整个目录结构 建立ext工程(扩展环境) (1)在myeclipse下,切换到resource视图模式,展开portal工程目录,我们可看到一个release.properties文件, 实际上我们要建一个它的扩展配置文件, 文件名为release.${username}.properties。 ${username}是计算机当前用户名,比如administrator,apple等等. 在计算机开始菜单运行cmd出来的 c:\document and setting\username>。 为什么非得计算机当前用户名,因为portal用了ant作deploy,里面有个xml配置文件使用了系统环境变量。懒得 去修改配置文件,就照它要求做。 我文件名是release.avidis.properties,文件内容只一行: lp.ext.dir=e:/cmproject/ext 即扩展工程放置路径。 (2)打开myeclipse里面ant视图(window--> show view --> ant) , 在ant视图中,点击添加,选择e:/cmproject/portal 目录下build.xml 顺序执行clean ,start ,build-ext 成功的话,在e:/cmproject/ext目录下产生一系列的文件和目录。 有时候在执行过程中会失败,报错。主要是portal工程本身没有compile完整。将portal重新build (project--build automatily)选择上,注意, 让build完成后,再执行clean ,start ,build-ext完成标志是myeclipse 右下角进度条完成100%。 (3)将 liferay-portal-tomcat-jdk5-4.1.0.zip解压到 e:/cmproject/ext/server/tomcat下,在e:/cmproject/ext 目录下我们可以看到app.server.properties文件, 同样我们也要建立一个扩展配置文件 app.server.${username}.properties,文件内容两行: lp.ext.dir=e:/cmproject/ext app.server.type=tomcat (4) 同样建立一个java project。工程名为ext.在myeclipse的Navigator里面可以看到ext工程的目录结构。 配置ext工程tomcat服务器设置 (1) 打开 window --> preference -->myeclipse--> application servers 将其他应用服务器disabble掉, 找到tomcat5,将tomcat home diretory 指向D:\cmproject\ext\servers\tomcat,展开tomcat5,jdk选择我们配置好的jdk1.5 Jdk选项下面 optional jave vm argument输入如下内容: -Xms256m -Xmx512m -Djava.security.auth.login.config=d:/cmproject/ext/servers/tomcat/conf/jaas.config (2) 将E:\cmproject\ext\servers\tomcat\conf\Catalina\localhost目录下的ROOT.xml文件内容修改为: <Context path="" docBase="ROOT" debug="0" reloadable="true" crossContext="true">
<Resource name="jdbc/LiferayPool" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="liferay" password="liferay" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://192.168.1.101/lportal"> </Resource>
<Resource name="mail/MailSession" auth="Container" type="javax.mail.Session" mail.transport.protocol="smtp" mail.smtp.host="localhost">
<Realm className="org.apache.catalina.realm.JAASRealm" appName="PortalRealm" userClassNames="com.liferay.portal.security.jaas.PortalPrincipal" roleClassNames="com.liferay.portal.security.jaas.PortalRole" debug="99" useContextClassLoader="false"> </Context> 建立ext工程数据库 (1) 在服务器上192.168.1.101安装建mysql数据库服务。 (2) 在192.168.1.101数据库上执行了E:\cmproject\ext\sql\create下的create-mysql.sql (3)在mysql数据库上建立用户名为liferay,password =liferay,并将databse为lportal的所有权限授予liferay。 (lportal是create-mysql脚本自动建立的) (4) 解压mysql-connector-java-3.1.12.zip, 将mysql-connector-java-3.1.12-bin.jar 拷贝到e:\cmproject\ext\servers\tomcat\common\lib下。使mysql的jdbc启动程序正常可用。 以上所有步骤顺利完成后,启动myeclipse 里面tomcat服务,启动正常的话,在浏览器里输入http://localhost:8080 可以看到portal系统了。
portlet工程开发简单说明 我们看到无论是portal和ext工程,目录都很繁杂,其实我们只要关注2个目录就够了。portal里面的portal-ejb 和portal-web。Portal-ejb是portal工程已经实现的所有portlet的java代码和部分资源文件.portal-web目录是放置 网页文件和portal的配置文件。 ext工程对应目录是ext-ejb,和ext-web。portal-ejb是放置我们自己开发的portlet的java代码。ext-web是自己开 发portlet对应的网页文件和配置文件。 下面我们来新建一个自己portlet。 这里我们采用portal里面代码规范生成机制。对于持久化层和服务层的类都可以自动产生。我们的portlet功能很 简单就是从数据库里面一个表中获取数据,并在页面上显示。 建立业务数据表 在数据库里面新建一个表a_user,字段userid,username,password.并往表中插入几个条数据。 建立代码模板配置文件 (1)建立service.xml文件 在ext-ejb/src/com/ext/portlet 新建一个目录myuser,在目录下建立一个service.xml文件 文件内容为: <?xml version="1.0"?> <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 4.0.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_4_0_0.dtd"> <service-builder root-dir=".." package-path="com.ext.portlet"> <portlet name="Reports" short-name="Reports"> <entity name="ReportsEntry" local-service="false" remote-service="true" persistence-class="com.ext.portlet.reports.service.persistence.ReportsEntryPersistence">
<!-- PK fields -->
<column name="entryId" type="String" primary="true">
<!-- Audit fields -->
<column name="companyId" type="String"> <column name="userId" type="String"> <column name="userName" type="String"> <column name="createDate" type="Date"> <column name="modifiedDate" type="Date">
<!-- Other fields -->
<column name="name" type="String">
<!-- Order -->
<order by="asc"> <order-column name="name" case-sensitive="false"> </order>
<!-- Finder methods -->
<finder name="CompanyId" return-type="Collection"> <finder-column name="companyId"> </finder> <finder name="UserId" return-type="Collection"> <finder-column name="userId"> </finder>
<!-- References -->
<reference package-path="com.liferay.portal" entity="User"> </entity> <exceptions> <exception>EntryName</exception> </exceptions> </service-builder>
<!--package-path是指我们即将建立portlet的上级目录--> <!-- portlet name就是我们新建文件夹名称myuser,short-name没有作研究不太清楚使用途径--> <!--entity name 是和我们即将建立的和数据库表a_user一一对应实体的类名,可以和数据库表名不同, 但为方便起见一般和表名保持一致--> (2)修改ant文件,增加ant任务 建好service.xml文件后,我们在ext-ejb目录下打开build-perent.xml 在 <target name="build-service"> ……. </target> 下面添加任务 <target name="build-service-portlet-usertest"> <antcall target="build-service"> <param name="service.file" value="src/com/ext/portlet/myuser/service.xml"> </antcall> </target> 然后在myexlipse的ant视图里面打开ext-ejb目录下的build.xml执行build-service-portlet-usertest任务。 我们发现在ext-ejb/src/com/ext/portlet/myuser下面多了几个目录和文件。这是都是系统自动产生的 ebernate的实体类和持久化类。如果我们再细心些也可发现在ext-ejb\classes\META-INF目录下配置文件 都多些内容。系统已经自动将对应的实体类、持久化类、工具类等配置为相应的javabean、ejb、webservice等 。无疑节省了很多时间,而且减少我们人工配置的错误。
业务实现编码 现在我们要实现一个查询功能,将数据库中表名a_user中所有记录的username查询出来,并显示在前台。 打开myuser/service/Persistence下a_userPersistence.java文件,建立一个方法名为findAllUsername:
public List findAllUsername () throws SystemException { Session session = null; try { session = openSession(); StringBuffer query = new StringBuffer(); query.append("FROM com.ext.portlet.myuser.model.a_user "); Query q = session.createQuery(query.toString()); q.setCacheable(true); return q.list(); } catch (HibernateException he) { throw new SystemException(he); } finally { closeSession(session); } }
返回表a_user所有记录,并以list方式存储。题外话,一般系统已经自动产生了主要字段的查询方法, 我们可以直接拿来用或者稍作改动都可以使用。 按一般惯例,a_userPersistence一般是不暴露给外面类,我们都是通过它的一个持久化辅助类来调用。 打开a_userUtil.java,同样在里面增加方法findAllUsername public static java.util.List findAllUsername () throws com.liferay.portal.SystemException { return getPersistence().findAllUsername (); } 然后我们在spring的service层同样增加一个方法。Service层的接口a_userLocalService里面增加一个函数 public List getAllUsers() throws SystemException; 在Service层接口a_userLocalService的实现a_userLocalServiceImpl.java增加对应方法,并调用持久层辅 助类userUtil方法findAllUsername public List getAllUsers() throws SystemException { return a_userUtil. findAllUsername (); } 同样spring的service层 也是通过辅助类作为对外唯一入口,所以在a_userLocalServiceUtil里面增加一 个方法findAllUsername作为service层的方法findAllUsername的入口。 public static List getAllUsers() throws SystemException{
try{ a_userLocalService service = a_userLocalServiceFactory.getService(); return service.getAllUsers(); }catch (SystemException se) { throw se; } catch (Exception e) { throw new com.liferay.portal.SystemException(e); }
} 需要注意的是service层接口对应具体实现是由工厂类指定。他们捆绑关系可以查看spring配置文件信息。 在执行ant 的build-service-portlet-usertest任务已经完成了。 在myuser/action目录下建立一个ViewUserAction.java文件,完成响应客户端请求。 public class ViewUsersAction extends PortletAction {
public ActionForward render( ActionMapping mapping, ActionForm form, PortletConfig config, RenderRequest req, RenderResponse res) throws Exception {
if (req.getWindowState().equals(WindowState.NORMAL)) { return mapping.findForward("portlet.ext.myuser.view"); } else {
List users = a_userLocalServiceUtil.getAllUsers(); List usernames = new ArrayList(); for (int i=0;i<users.size();i++){ usernames.add( ((a_user) users.get(i)).getUsername()); } req.setAttribute("users", usernames);
return mapping.findForward("portlet.ext.myuser.view_users"); } } } 里面大概功能是如果porlet的窗口状态时普通,则定向到一个叫portlet.ext.myuser.view的目标上。 如果窗口状态是最大化,那么就从调用userLocalServiceUtil,从数据库里面获取所有人员信息。 Portlet的生成 建立自己的portlet。在myuser下面新建文件UsersPortlet.java public class UsersPortlet extends StrutsPortlet { public void doView(RenderRequest req, RenderResponse res) throws IOException, PortletException {
PortletPreferences prefs = req.getPreferences();
System.out.println(prefs.getValue("user", ""));
super.doView(req, res); } } 该portlet重载了doview方法。如果自己portlet对view和edit有自己特性,那么只要重载doview和doedit就可以了。 现在portlet的内容是空的,我们用jsp页面来展示用户名称方式来填充portlet里面内容。 在 ext-web/docroot/html/portlet/ext目录下建立目录myuser,并在myuser目录下建立init.jsp文件
<%@ include file="/html/common/init.jsp" %>
<portlet:defineObjects>
<% PortletPreferences prefs = renderRequest.getPreferences();
建立view.jsp文件:
<%@ include file="/html/portlet/ext/myuser/init.jsp" %> <a href="<portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>">"> MyUser <%= prefs.getValue("user", "") %> </a> 该jsp内容是显示默认的初始用户名。具体值从初始化配置参数里获取。
建立view_users.jsp <%@ include file="/html/portlet/ext/myuser/init.jsp" %> <% List reports = (List)request.getAttribute("users");%>
<% for (int i = 0; i < reports.size(); i++) { String reportName = (String)reports.get(i); %>
<%= reportName %><br>
<% } %> 该jsp页面目的是展示所有从数据库里面取出来的用户名。
Ok,完成以上工作后,我们整个portlet编码工作已经宣告结束,接下来的是配置portlet 参数工作。 Portlet的配置
是portlet配置信息文件存放Ext-web/web-inf目录下,在port-ext.xml文件里面添加
<portlet> <portlet-name>EXT_users</portlet-name> <display-name>myusers</display-name> <portlet-class>com.ext.portlet.myuser.UsersPortlet</portlet-class> <init-param> <name>view-action</name> <value>/ext/myuser/view_users</value> </init-param> <expiration-cache>0</expiration-cache> <supports> <mime-type>text/html</mime-type> </supports> <resource-bundle>com.liferay.portlet.StrutsResourceBundle</resource-bundle> <portlet-preferences> <preference> <name>user</name> <value>jack</value> </preference> </portlet-preferences> <security-role-ref> <role-name>power-user</role-name> </security-role-ref> <security-role-ref> <role-name>user</role-name> </security-role-ref> </portlet>
<portlet-name>必须唯一,不得已有portlet名字冲突。<display-name>也必须唯一。 <portlet-class>指向我们的建立portlet类。 <name>view-action</name>里面值是指view这个action对应的actionurl。<portlet-preferences> 里面参数值是提供给这个portlet使用的参数初始值。这里配置是指portlet里面使用到参数名user的值是jack。 如portlet不需要初始值参数,则该项不需要配置。
在liferay-portlet-ext.xml文件里面添加 <portlet> <portlet-name>EXT_users</portlet-name> <struts-path>ext/myuser</struts-path> <use-default-template>false</use-default-template> </portlet>
<portlet-name>的值必须和portlet-ext.xml文件里面<portlet-name>值一致。
在liferay-display。Xml文件节点<category name="category.test"> 下面添加 <portlet id="EXT_users"> id必须和portlet-ext里面的<portlet-name>一致。
在struts-config.xml文件里面添加内容: <action path="/ext/myuser/view_users" type="com.ext.portlet.myuser.action.ViewUsersAction"> <forward name="portlet.ext.myuser.view_1" path="portlet.ext.myuser.view"> <forward name="portlet.ext.myuser.view_users_1" path="portlet.ext.myuser.view_users"> </action>
就是说,当前台提交一个actionUrl为/ext/myuser/view_users请求的时候,由ViewUsersAction负责处理这个 action操作。后面2个forward指的是在ViewUsersAction定向返回请求目标页面。 ………… return mapping.findForward("portlet.ext.myuser.view_1");
……… return mapping.findForward("portlet.ext.myuser.view_users_1");
findForward的值为避免与其他findForward值冲突,一般将包名也带上,保证不会重名。
在tiles-defs.xml文件里面添加内容: <definition name="portlet.ext.myuser.view" extends="portlet"> <put name="portlet_content" value="/portlet/ext/myuser/view.jsp"> </definition> <definition name="portlet.ext.myuser.view_users" extends="portlet"> <put name="portlet_content" value="/portlet/ext/myuser/view_users.jsp"> </definition>
该name的值即随同struct-config.xml配置信息里面forward参数path值对应的,指向真正的目标页面。
最后我们在ext-ejb/classes/content目录下language-ext.properties文件里面增加内容: javax.portlet.title.EXT_user=MyUsers 即portlet显示出来时候,在portlet上面标题信息。
Portlet常见问题 1. 运行提示portlet path 找不到,则一般是liferay-port-ext文件里面portlet的struts–path有问题。 2. 启动提示jaas.config错误,没有在tomcat的jdk参数配置jaas.config文件或配置路径不对 3. 提示html/../..找不到,一般是struts-config文件里面path路径有问题。 4. 有执行和数据库存取数据时候,提示“columnname_”字段不存在,去修改ext-hbm.xml文件,ant执行 build service任务时候,产生ext-hbm.xml信息有时会不准确,将对应的<property name="columnname" column="columnname_ ">的column调整为数据库对应正确的字段名。 5. 大家在清除不用的portlet时候,请先登录系统,将不用的portlet关闭,然后再删除或屏蔽对应的代码。 不然直接删除或屏蔽代码,重新启动后,会提示portlet找不到。注册后的portlet会写信息到数据库中。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
返回顶楼 |
|
|
- smallgoldstone
- 等级: 初级会员
- 性别:
- 文章: 2
- 积分: 30
|
好文章,希望有更多的关于portlet的文章出来
|
返回顶楼 |
|
|
- nwyxqb123@163.com
- 等级: 初级会员
- 性别:
- 文章: 1
- 积分: 30
- 来自: 上海
|
想问下,在自己配置service.xml时,总是会出个空指针异常,代码如下
[java] log4j:WARN No appenders could be found for logger (com.liferay.portal.util.EntityResolver).
[java] log4j:WARN Please initialize the log4j system properly.
[java] java.lang.NullPointerException
[java] at java.io.Reader.<init>(Reader.java:61)
[java] at java.io.InputStreamReader.<init>(InputStreamReader.java:55)
[java] at com.liferay.util.StringUtil.read(StringUtil.java:257)
[java] at com.liferay.util.StringUtil.read(StringUtil.java:253)
[java] at com.liferay.portal.tools.ServiceBuilder.getEntity(ServiceBuilder.java:703)
[java] at com.liferay.portal.tools.ServiceBuilder.<init>(ServiceBuilder.java:580)
[java] at com.liferay.portal.tools.ServiceBuilder.<init>(ServiceBuilder.java:324)
[java] at com.liferay.portal.tools.ServiceBuilder.main(ServiceBuilder.java:82)
build-ejbxml:
[java] log4j:WARN No appenders could be found for logger (com.liferay.portal.util.EntityResolver).
[java] log4j:WARN Please initialize the log4j system properly.
|
返回顶楼 |
|
|