搭建开发环境
安装
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
会写信息到数据库中。