Liferay Service Build(II)
来源:互联网 发布:java回文数 编辑:程序博客网 时间:2024/05/11 14:35
上文中,大致地介绍了Liferay的 Service build的功能,也算是对Service Build有了一个感性的认识了。
从本文开始,将通过一个例子来讲解service build的使用方式,并对其中可能涉及到的一些liferay的代码进行讲解,来一步一步地研究Service build和Liferay。当然,本人此处所写的内容仍旧来自Liferay in Action一书中(仍建议阅读原文),如果阅读的过程中出现有什么疑问或者有什么想法,欢迎留下意见与建议。
简单来说,该例子就是一个在Liferay环境下的,具有增删改查功能的工程。但是与以往基于纯Tomcat环境下的工程不同,这里不仅会涉及到Liferay的特性(如AUI标签),也会涉及到一些其他的内容(如JSTL标签)。文中不会对其进行介绍,感兴趣的同学请自行Google。.
下面,就逐步地来讲解。
1. 构建Service.xml
该文件的一般形式与作用在前一篇文章已经给出,此处不再赘述。该工程中
所涉及到三个数据表如下:
数据表1:f_fproduct
ColumnName
Datatype
PK
NN
FK
productId
INT(20)
*
*
productName
String(75)
serialNumber
String(75)
companyId
INT(20)
*
groupId
INT(20)
*
数据表2:f_fregistration
ColumnName
DataType
PK
NN
FK
registrationId
INT(20)
*
*
fUserId
INT(20)
datePurchased
DATETIME
serialNumber
VARCHAR(75)
productId
INT(20)
companyId
INT(20)
groupId
INT(20)
数据表3:f_fuser
ColumnName
DataType
PK
NULL
FK
fUserId
INT(20)
*
*
firstName
String(75)
Address1
String(75)
City
String(75)
State
String(75)
String(75)
Country
String(75)
birthDate
DATETIME
Male
TINYINT
userId
INT(20)
*
companyId
INT(20)
*
groupId
INT(20)
*
而与之对应的Service.xml文件内容如下所示(注:这里最终的文件内容,不是初期就一次性写成的):
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEservice-builderPUBLIC"-//Liferay//DTD Service Builder 6.0.0//EN"
"http://www.liferay.com/dtd/liferay-service-builder_6_0_0.dtd">
<service-builderpackage-path="com.productregistration">
<author>Feng</author>
<namespace>F</namespace>
<entityname="FProduct"local-service="true"remote-service="false"><!—A-->
<!-- PK Fields -->
<columnname="productId"type="long"primary="true"/>
<!-- Other Fields -->
<columnname="productName"type="String"/>
<columnname="serialNumber"type="String"/>
<!-- Foreign Keys -->
<columnname="companyId"type="long"/>
<columnname="groupId"type="long"/>
<!-- Order -->
<orderby="asc">
<order-columnname="productName"/>
</order>
<!-- Finder Methods -->
<findername="G_PN"return-type="Collection">
<finder-columnname="groupId"/>
<finder-columnname="productName"/>
</finder>
<findername="GroupId"return-type="Collection">
<finder-columnname="groupId"/>
</finder>
<findername="CompanyId"return-type="Collection">
<finder-columnname="companyId"/>
</finder>
</entity>
<entityname="FUser"local-service="true"remote-service="false">
<!-- PK Fields -->
<columnname="fUserId"type="long"primary="true"/>
<!-- Other Fields -->
<columnname="firstName"type="String"/>
<columnname="address1"type="String"/>
<columnname="city"type="String"/>
<columnname="state"type="String"/>
<columnname="email"type="String"/>
<columnname="country"type="String"/>
<columnname="birthDate"type="Date"/>
<columnname="male"type="boolean"/>
<!-- Foreign Keys -->
<columnname="userId"type="long"/>
<columnname="companyId"type="long"/>
<columnname="groupId"type="long"/>
<!-- Relationships -->
<columnname="userRegistrations"type="Collection"entity="FRegistration"
mapping-key="fUserId"/>
<!-- Order -->
<orderby="asc">
<order-columnname="firstName"case-sensitive="false"/>
</order>
<!-- Finder Methods -->
<findername="G_LN"return-type="Collection">
<finder-columnname="groupId"/>
<finder-columnname="firstName"/>
</finder>
<findername="G_E"return-type="Collection">
<finder-columnname="groupId"/>
<finder-columnname="email"/>
</finder>
<findername="G_U"return-type="Collection">
<finder-columnname="groupId"/>
<finder-columnname="userId"/>
</finder>
</entity>
<entityname="FRegistration"local-service="true"
remote-service="false">
<!-- PK Fields -->
<columnname="registrationId"type="long"primary="true"/>
<!-- Other Fields -->
<columnname="fUserId"type="long"/>
<columnname="datePurchased"type="Date"/>
<columnname="serialNumber"type="String"/>
<columnname="productId"type="long"/>
<columnname="companyId"type="long"/>
<columnname="groupId"type="long"/>
<!-- Finders -->
<findername="GroupId"return-type="Collection">
<finder-columnname="groupId"/>
</finder>
<findername="G_RU"return-type="Collection">
<finder-columnname="groupId"/>
<finder-columnname="fUserId"/>
</finder>
<findername="G_DP"return-type="Collection">
<finder-columnname="groupId"/>
<finder-columnname="datePurchased"/>
</finder>
<findername="G_SN"return-type="Collection">
<finder-columnname="groupId"/>
<finder-columnname="serialNumber"/><!--password -->
</finder>
</entity>
</service-builder>
下面,我们来分析一下这个配置文件.
先从简单的开始,如下图。
1-3行的意义自不必说。
第4行中,<service-builder/>元素签是整个配置文件的基础,所有对该文件的配置都是在<service-builder/>内部完成的。其中,package-path是指定所在包的路径。在Build后,就会以”com.productregistration”为统一的包前缀名来生成相应的层次包。但要注意的是,此处所指定的path至少应该包含在所创建的portlet的包中。
第5行指定作者,以表明责任人。
第6行指定命名空间,一是为了防止可能存在的命名重复,二是指定了所生成的数据表的前缀,利于区分,如以上三个表的名称格式,就是在Service Build后所形成的。
下面,我们开始分析第一个实体。内容如下:
在第7行中,指定实体名称,及将要生成的数据表的名称为FProduct,类型为本地服务。8-12行指定数据表内字段名称与类型,13-14行指定外键,17-19行指定以productName的正序来排列。21-24行,是指定了一个查找的方法,生成后的方法名称为findByG_PN并指定返回类型为Collection,即合集。而且在该方法中,需要程序员指定groupId和productName这两个变量。系统在Service Build后,不会直接在接口和Util里生成find方法的,而是在在Persistence里来生成方法。如果我们
需要在接口和Util类中使用的话,需要在Util类中自写定义的方法,并重新Service Build,则会自动地加入到接口和Util类中(推荐阅读上传的《liferay中service.xml元素解释》)。
在定义第一个实体后,就可以Service Build一下了。来生成对应的层次包了,如果没有错误,控制台将出现以下内容:
表明成功Build。同时也会生成如下的层次结构:
除此之外,还会在docroot/WEB-INF/src下生成新的META-INF文件夹,在WEB-INF下生成service和sql文件夹。此处不再一一展示其内容,请实际操作并查看。
这样,第一次的Service Build就完成了,下面开始进行代码的书写,逐步地实现功能。
2 添加代码
2.1纯粹的功能实现
观察所生成的层次结构,需要进行第一次改动的,就是在
com.productregistration.service.impl这个包中的FProductLocalServiceImpl.java文件中。
其实,Service Build所产生的结构层次,所运用就是面向接口编程的思想,(关于该思想的好处以及具体内容,此处只作提及,并不予以说明。请自行查找资料),我们所需要实现的方法,基本上就是在XXX.service.impl下的相应文件来实现的,之后,通过一层层的调用来最终实现功能,减低代码间的耦合,方便源码管理。
我们来看FProductLocalServiceImpl.java中的内容:
应当注意注释里的话,它说明了一切。
来看具体的代码,这里重点区解释一些变量,因为这些变量的具有以下特点:系统生成,数量众多,功能强大。但往往我们却不知道它们有哪些,有什么用以及在哪。
变量fProductPersistence的声明在FProductLocalServiceBaseImp.javal中,这是用系统生成的持久类变量,通过对该文件的观察,你会发现很多有用的东西。后面的create(long Id)方法位于FProductPersistence.java中,作用是通过主键在数据库来创建一个新的product,并通知适当的层次监听器(create a new f product with the primary key from the database.Also notifies the appropriate model listerners)。
变量counterLocalService同样位于FProductLocalServiceBaseImpl.java中,所在的类为CounterLocalService,increment()方法的作用是初始化一个新的以FProduct.class.getName()为名字的计数器,该方法较为常用。该处语句的意义就是在添加数据实体的时候非主键会自动递增。在我所看到的而资料中,说明liferay中并不是使用hibernate的自动递增,而是使用CounterLocalService这样能够更好的屏蔽数据库的差异性(求大神解释)。54行中的变量resourceLocalService同样位于FProductLocalServiceBaseImpl中,该变量通过addResources()方法来保存增加的数据(我没有找到addResources()方法的具体说明以及其所在类的类说明)。
以上的代码的作用就是实现添加产品的功能。下面来总结一下:
第一步,就是创建一个新的Fproduct对象。之后用fPersonPersistence变量通过Spring将注入相应的类中。
第二步,就是调用resourceLocalService来保存实体并创建相应的权限。
最后,就是通过set方法和update方法来完成添加功能。
2.2 结合Liferay的MVC
但是要注意到,该代码是在service.impl中实现的,而工程是基于Portlet的,所以我们就要在对应的portlet类里来再次写一个”add”方法,通过对service.impl中的add方法的调用,并结合一些界面信息的显示功能,才算是完成了一个Portlet下的基于MVC模式的添加功能。代码如下图:
在这段代码中涉及到了很多内容,ThemeDisplay是Liferay的内置对象,ActionUtil和ProdRegValidator都是自定义的方法集合,这两个方法的具体内容将以附录的形式给出。在此处,主要是添加了一些检验和错误提示的功能。
首先,productFromRequest()的功能就是得到用户所提交表单的FProduct对象,之后,通过ValidateProduct()来验证对象的有效性,并进行下一步的操作。43行就是调用了上面所写的addProduct()方法。
2.3 JSP页面代码
在这一小节中,主要涉及到一些Liferay的界面编程内容,Liferay中,推荐使用AlloyUI(AUI)标签元素来进行界面编程,在这里不做过多的介绍,通过下面的截图,相信就可以对它有一个初步的了解了。当然,并不是在Liferay环境下就必须使用AUI来进行界面的编写工作。
好,下面来看看和上文代码对应的portlet的view.jsp文件内容,如下图:
31-36行的代码,就是我们根据不同需要而在页面上显示的校验信息,其中的key值是定义在一个属性文件中,在该属性文件中,定义了不同操作所对应的不同提示。37行定义了一个名为addProduct的actionURL并在下面的form中调用该action,注意,该出的name的名称要与代码中的名字一致。
这样,在liferay下就完成一个简单的添加的功能。
以上简单地介绍了Service Build的配置文件的内容意义以及在Liferay下借助Service Build功能如何进行基本的编程。介绍的还是比较简单,省去了一些对技术原理和一些技术内容的介绍。本文的目的是尽可能的为大家扼要的介绍Liferay下的编程技术,如果想获取更多的内容,还请大家能够尽量阅读原文,
如有错误,敬请指正。
Edited by FengJunlong
- Liferay Service Build(II)
- Liferay Service Build
- Liferay:关闭Portlet的自动更新功能(service.properties的build.auto.upgrade=false)
- liferay 点击build service 出现Cloud not reserve enough space for object heap
- liferay 6.1 web service 发布
- liferay get permissionChecker in service
- Liferay 6.1开发Service Builder
- memo:liferay-service-builder_6_2_0.dtd
- Transaction Management with Liferay Service
- liferay学习笔记:Service layer
- liferay-portal-6.2 create liferay portlet plugins project build failed
- 新建liferay项目报BUILD FAILED错误
- opensuse build service open build service
- Segment Tree Build II
- Build Post Office II
- Liferay:Service Builder的DTD内容
- Liferay service builder connects with other database
- liferay json web Service 注册问题
- C语言学生信息管理系统(动态链表版559)【不会】
- 许一世情 陪你 浪尽天涯
- 最少操作数
- linux解压缩xz文件
- winpcap使用经验
- Liferay Service Build(II)
- 青春划过指尖
- C语言求高精度PI【没看】
- 给IT新人的15个建议,也是老程序员的反省和总结
- VisualSVN Server 导入已存在的库
- STL使用误区
- C语言身份证信息查询系统(可验证输入身份证是否合法)【已会】
- 策略模式(Strategy Pattern)
- 黑马程序员之C#学习笔记:关于继承