目录
一、创建一个单独的mvc-portlet工程(基于gradle,也可以基于maven见目录二、部分)
二、创建mvc-portlet工程--搭配service-builder工程(基于maven)
基于gradle的Liferay 和 基于maven的Liferay:
一、创建一个单独的mvc-portlet工程(基于gradle,也可以基于maven见目录二、部分)
1. 创建过程参考
目录结构:
选择服务时候,选择这个,上面的文件夹应该是多余的下载了(已删除):
部署按钮在右侧边栏Gradle中:
bnd.bnd文件:
Bundle-Name:liferay应用程序管理界面显示的
portlet名称应用程序名称。Bundle-Vertsion:liferay应用程序管理界面显示的版本。
Export-Package:值是工程目录,指向
也对应示例中的portlet名称,示例中的portlet名称可以重复:
2. 解决乱码
后台:在builed.gradle文件添加
tasks.withType(JavaCompile) {//解决后台中文乱码 options.encoding = 'UTF-8' }
jsp页面:第一行添加
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8"%><!--解决页面乱码放第一行-->
二、创建mvc-portlet工程--搭配service-builder工程(基于maven)
1. Service Builder:
是Liferay Portal提供的一种代码生成方案,用来和数据库打交道,开发人员只需要编辑数据库的实体描述文件,即可根据此XML文件生成Spring层代码、Hibernate层代码、SQL、SQL索引创建文件、Spring和Hibernate的配置文件等,简化了开发周期。简单来说,就是根据数据库描述文件,生成service层和持久化层的代码,开发人员只需要关注控制层即可。
主要作用:简化开发周期,使定制化开发的代码保持规范性和一致性
实现原理:基于Freemarker的模板代码生成方案,生成代码的逻辑在源码的如下包路径下面:com.liferay.portal.tools.servicebuilder
2. 文章记录:
liferay 7.2.0第一个小程序idea版 GuestbookPortlet_01 - 灰信网(软件开发博客聚合)
liferay 7.2.0第一个小程序idea版 GuestbookPortlet_02 - 灰信网(软件开发博客聚合)
liferay7.3.5开发学习(四)- service-builder - 外星鸟 - 博客园
service.xml其中:
namespace为表名的前缀
entity里面的name为表生成实体后的名字,默认也是表名,如果想指定表名,要用table属性。
column:为表中字段,name为默认实体属性名也为数据库表字段名,想指定字段的话用db-name, type为字段类型,这里的字段类型为Java中的数据类型。
如果是主键,添加primary=true属性。
order为排序方法,字段名指定前面column里面的name值。
3. 目录结构:
三、Liferay表结构介绍(二):用户组织机构相关
Liferay表结构介绍(二):用户组织机构相关
参考:http://www.huqiwen.com/2016/06/05/liferay-database-referee-1-user-organization-tables/
用户和组织机构相关的表主要有user_、contact_、organization_、users_orgs等
user_用户表
userId:用户Id。
defaultUser:是否默认用户,1是默认用户,0为否。默认用户为系统里面的默认用户,做一些特殊场景下的权限和获取相关信息的,不可用于登录和具体的业务处理,一般一个实例有一个默认用户。
contactId:关联到contact_表的外键,存储contactId。
password_:存储的密码,一般是加密过后的密码的hash值,具体的加密方法是在portal.properties里面进行的配置。
passwordEncrypted:是否加密,一般都是加密的,除了默认用户其他的都是1。
passwordReset:密码是否需要重置,如果为1,则用户在下一次登录的时候会让他重新设置密码,可以在用户管理密码处进行修改。
digest:用户email、屏幕名称、userId的MD5的hash值。
reminderQueryQuestion:密码找回时的问题。
reminderQueryAnswer:密码找回时的答案。
graceLoginCount:宽限登录次数,一般是在密码策略的密码到期时的设置。
screenName:屏幕名称。
emailAddress:邮件地址。
facebookId:使用facebook登录的时候的facebookId。
ldapServerId:ldap服务器里面的信息,用ldap导入时有此值。
openId:使用openid进行登录时,用户的绑定的openid的信息。
portraitId:用户的头像的图片ID,对应于image表里面的主键。
languageId:当前用户的显示语言,在用户管理的显示设置中进行修改,用户登录后会将local信息改为此信息。
timeZoneId:用户的时区。
greeting:用户的问候词,在某些应用里面可以单独设置,比如有些系统中,有些人是领导,可以单独设置为,欢迎xxx领导。
comments:用户评论,可以看作类似备注,可以在用户管理处进行修改。
firstName:用户的名字。
middleName:中间名。
lastName:姓。
jobTitle:用户职称。
loginDate:用户本次登录时间。
loginIP:登录的IP。
lastLoginDate:用户上次登录时间。
lastLoginIP:上次登录的IP。
lastFailedLoginDate:上次登录失败的时间。
failedLoginAttempts:登录失败次数。可以配置成超过指定的次数,则出现验证码等。
lockout:是否锁定。
lockoutDate:锁定时间。
agreedToTermsOfUse:用户是否已经同意了用户协议。
emailAddressVerified:邮件地址是否已经验证。
status:用户状态。
contact_表,联系信息表
此表和一般和用户的信息一一对应,可以看作是用户信息的扩展。在代码中一般不操作contact信息,可以通过user对象进行信息的获取与设置。只描述重要的字段。
userId:用户Id,对应于user表里面的相关信息。
userName:用户名称。
classNameId:这里一般为20005,对应于classname表里面的用户的对象。
classPk:对象的主键,一般为这里为用户的ID,看到这两个字段,就可以明白contact可以应用于其他对象,不止是用户。
accountId:对应于当前记录所对应的companyId所对应的accountId。一般一个实例下的都是相同的。
parentContactId:父级contact,一般为0;
emailAddress:邮件地址。
prefixId:前缀。
suffixId:后缀,这里的前缀和后缀是存的常量值,主要是方便用来作国际化。
male:性别,这里存的是是否男性。
birthday:生日。
smsSn、aimSn、facebookSn、icqSn、jabberSn、msnSn、mySpaceSn、skypeSn、twitterSn、ymSn各社交平台的帐号信息,其中的大部分在7.0里面已经废弃。
employeeStatusId:员工状态ID。
employeeNumber:员工编号。这两个字段可以用来做内部的信息编码显示处理。一般为空。
jobTitle:职称。
jobClass:工作类别等。可以根据自己的需要进行填充,没有特别的业务,可以当作liferay预留的扩展字段。
hoursOfOperation:工作小时,同上。
organization_机构表
organizationId:机构ID。主键。
companyId:实例ID。
userId:创建当前机构的用户ID。
userName:创建当前机构的用户名称。
parentOrganizationId:上级机构的Id,用来做树形结构。
treePath:保存的是organizationId树形层级结构。
name:机构名称。
type_:机构类型,是常规机构还是地点。location和regular-organization两种类型。
recursable:是否允许递归,此值为true,没有地方提供更改。
regionId:地区ID。对应region表。
countryId:国家ID。对应country表。
statusId:状态ID,默认不12017,取自portal.properties里面的sql.data.com.liferay.portal.model.ListType.organization.status配置。
comments:备注信息。
Usegroup表,用户组表
liferay的用户组,算是一个特殊用户的组合,区别于组织机构,可以为将用户组当成一个集合使用,比如有些机构里面,我们可能会需要一个领导层的用户组。
name:用户组的名称。
description:描述。
parentUserGroupId:上级用户组的Id。
addedByLDAPImport:是否是从LDAP里面导入的。
四、Liferay表结构介绍(三):站点及页面相关表
Liferay里面的所有的站点信息都是保存在group表里面,包括普通站点、组织机构站点、用户组站点、用户的私人站点,模板站点等。
Group_表 站点表
groupId:站点Id。
companyId:实例Id。
creatorUserId:创建当前站点的用户Id。
classNameId:是哪个实体的站点,比如20003是组织机构,20001是普通站点,20005是用户,对应于classname表里面的相关信息。
classPK:对应实体的主键。
parentGroupId:上级站点的ID。
liveGroupId:远程活动的站点,一般情况下此站点为0,当在站点设置,待发布那里启用本地在线时,会生成一个本地的group,此处放的是对应的远程的groupId。
treePath:站点如果层级结构。
name:站点名称。
description:站点描述。
type_:站点类型,用来设置此站点的成员的加入方式,1是开放的,2是受限制的,3是私有的,可以在站点设置中修改,会有资格类型既是存储在此字段中。
typeSettings:站点的一些其他的设置,在站点设置中的其他的相关字段的配置,都是存储在此字段中,比如语言、是否启用回收站等。
manualMembership:是否允许手动的管理成员。
membershipRestriction:是否限制上级站点成员,当站点是子站点的时候此字段有用,为是否限制上级站点的成员访问此站点。
friendlyURL:友好的URL信息。
site:是否站点。存在group里面的并不是都是站点,比如站点模板。
remoteStagingGroupCount:作用暂时未知。
active_:站点是否处于激活状态。
layoutSet 页面集表
我们在站点的页面管理中,看到的公有页面、私有页面就是这个的集合的存储信息。
layoutSetId:主键
groupId:所属的站点Id。
companyId:所属的实例Id。
privateLayout:是否私有页面。
logo:是否有logo。
logoId:logo对应的图片id,对应于image表中的id。
themeId:使用的是哪个主题,对应于主题配置文件中的id。
colorSchemeId:主题使用的是哪个的颜色方案,多方案主题是有用。
wapThemeId:wap版的主题,现在基本上已经没用,7.0已经废弃。
wapColorSchemeId:wap版对应的主题颜色方案。
css:在外观和风格那里配置的CSS信息保存在这里。
pageCount:当前页面集下面有多少个页面。
settings_:其他的一些配置信息,比如远程发布的时间,是否显示站点名称等的主题配置。
layoutSetPrototypeUuid:对应的站点模板的uuid,对应于layoutsetprototype表中的uuid。
layoutSetPrototypeLinkEnabled:是否启用模板的关联,也就是模板修改后,自动的同步到当前的页面集。
layout 页面表
plid:页面id。
groupId:所属的站点Id。
companyId:所属的实例Id。
privateLayout:是否私有页面。
layoutId:页面的id,此id从1开始进行计数,主要用来做树形的结构,一个页面集下面从1开始计数。
parentLayoutId:上面的页面id,是用的layoutid,而不是plid。
name:页面名称。XML结构用来存储不同语言的名称。
title、description、keywords、robots对应用于SEO里面的标题、描述、关键词,robots,如果是做外网的应用时方便搜索引擎优化时使用。
type_:页面类型,是普通的还是URL、还是iframe等。
typeSettings:页面的一些配置信息。比如当前页面使用的是哪个布局,当前的页面上有哪些portlet等。
hidden_:是否从导航中隐藏。
friendlyURL:页面的friendlyURL。
iconImage:此页面是否有图标。
iconImageId:图标的id,对应于image表里面的信息。
themeId:使用的是哪个主题,对应于主题配置文件中的id。
colorSchemeId:主题使用的是哪个的颜色方案,多方案主题是有用。
wapThemeId:wap版的主题,现在基本上已经没用,7.0已经废弃。
wapColorSchemeId:wap版对应的主题颜色方案。
css:在外观和风格那里配置的CSS信息保存在这里。
priority:可以看作是页面的排序号。
layoutPrototypeUuid:对应的页面模板的ID。
layoutPrototypeLinkEnabled:是否和页面模板关联。
sourcePrototypeLayoutUuid:源页面的ID,在启用远程发布时有用。
+++++++++++++++++++++++++++
layoutprototype为页面模板
layoutsetprototype为站点模板。
五、权限的存储
在Liferay里面存储权限的表主要涉及两个表,一个叫resourcepermission(资源角色权限表)。此表定义了Liferay里面权限结构,里面的表结构主要字段含义如下:
· Name:资源对象的描述,如果资源描述的是一个portlet对象,则为这个portlet对象的portletId.如果是一个class, 则为带包名的class全名称
· Scope:权限的作用域,值有1、2、3、4,1表示company级就是企业级、2表示group级就是站点级,3是站点模板,4是没级,就表示当前的。
· Primkey:资源的ID(不是该表的主键)
· Roleid:角色id
· Ownerid:资源的属于哪一个人,一般值为0或创建的用户id
· Actionids:这里的actionids为resourceaction表里面的bitwisevalue的值的相加之和。
这里重点字段有四个:Name确定资源的类型是portlet还是具体的modle还是其他的,primkey为资源的主键,我们通过资源类型和资 源ID就确定了一个具体的资源(具体某一个portlet,具体某一张图片等),Roleid确定的是角色,actionids这个确定的是具体的有哪些 可执行动作(查看、修改、删除等等)。
另外一张表为:resourceaction(资源动作表),此表定义了Liferay中的相应的资源上可执行的动作有哪些。主要的表结构字段如下:
· Name: 定义了资源的类型,同上面的表一样,确定资源是portlet还是实体或者是其他,表示是什么资源。
· actionId:可执行的动作名称,这里主要是为我们的动作启一个名称,如OVERRIDE_CHECKOUT、UPDATE_DISCUSSION、DELETE。
actionId列不存在对应的Action_表,所有的actionId定义在ActionKeys类中。import com.liferay.portal.kernel.security.permission.ActionKeys;
· bitwisevalue:这个定义的为上面可执行动作的位值,也可以看作是权限的动作ID。
上面介绍完这两个表了,那确定一个权限的过程是什么呢?比如我们要判断某一个用户是否拥有welcome页面的查看(VIEW)权限:
1. 根据用户,获取用户的角色,我们可以知道某一个用户拥有哪些角色。这一步应该没有啥疑问。
2. 在资源角色权限表里面询name值为com.liferay.portal.model.Layout(表示页面的资源类型)的,primkey为页面的当前页面Id的,roleid值为当前用户角色id的。(三者都不是resourcepermission表主键)。从而获取到Actionids。
3. 在资源动作表(resourceaction) 里查询name为com.liferay.portal.model.Layout(表示页面的资源类型),actionid为VIEW的记录中的bitwisevalue的值,假如值为1, 则我们现在只需要判断资源角色权限表(resourcepermission)里面的actionids是不是有1组成的即可。那怎么判断呢?
要判断bitwisevalue的值是否在actionids里面,只需要两个做位(与)运算,actionids & bitwisevalue是否等于bitwisevalue即可。
已知:用户 页面 用户查看页面
- 用户 =》用户角色
- 用户角色、页面 id 、资源类型为页面(Layout) =》Actionids
- 资源类型为页面(Layout)、actionid为VIEW查看 =》bitwisevalue
- 位(与)运算,actionids & bitwisevalue是否等于bitwisevalue,是有权限,否无权限