`

liferay学习系列(2)

阅读更多

想做个用户积分管理,类似于论坛积分的概念,首先在用户管理里面添加这个字段,并且用户不可以修改,可见,管理员可以为其添加积分:) 充人民币 给积分啦,当然你需要有好的资源,别人买你的服务。 主要是用了liferay的Expando:( 关于Expando, 就是解决所谓动态字段问题的一个技术。这个方案并不真正的修改原来的表,去增加一个字段,而是采用用四个表结构来存储所有其他表的扩展字段及值的一种方法。这四个表是:ExpandoTable, ExpandoColumn, ExpandoValue, ExpandoRow, 共同模拟:表、字段、行、一行中的某字段值。 )
ExpandoTable:
tableID companyId classNameId name
10702   10113      10039      DEFAULT_TABLE

注释:
ClassName_表中对应的模型对象: 100039 com.liferay.portal.model.User
Company 表的companyId实际就是instance(portal实例),对应Accout_  accountID 10115  companyId 10113
tableID 类似标识(counter_) 注意有缓冲的,这一点后面详细讲解

ExpandoColumn:
columnId companyId tableId name type_ defaultData typeSettings
10703    10113      10702  积分  15     0          height=105
                                                  indexable=0
                                                  hidden=0
                                                  width=450
                                                  secret=0
10705   10113       10702  test  15              indexable=true
建立这个属性后ExpandoRow,ExpandoValue 还为空

接下来为用户添加这个属性的值:)
ExpandoRow:
[rowId_][companyId][tableId][classPK]
10706   10113      10702   10145
关于classPK的解释:
“You can comment about some certain types of entities, say for example, a blog entry with pk 23, then classNameId will refer to a classname_ table row that holds value "com.liferay...BlogsEntry" and classPK will be 23.”

该用户的User_ userId为10145

ExpandoValue:
[valueId][companyId][tableId][columnId][rowId_][classNameId] [classPK][data_]

10707 10113 10702 10705 10706 10039 10145 test
10708 10113 10702 10703 10706 10039 10145 10

根据classNameId找到表 根据classPK找到记录,这样就可以吧属性附在该条记录上了

到这个地方liferay的expando表结构就理解完毕了

接下来时设置自定义属性的权限:
如果想访问自定属性:
可以参照:https://www.liferay.com/zh_CN/web/guest/community/forums/-/message_boards/message/3362117;jsessionid=14639200091A7D6C1BD59626A412AA2A

Hi,

using
12    List<ExpandoTable> expandoTables = ExpandoTableLocalServiceUtil3        .getExpandoTables(getStart(), getEnd());
you get all expando table definitions.

Using
12    String modelResource = "com.liferay.portal.model.Organization";3    List<ExpandoColumn> columns = ExpandoColumnLocalServiceUtil4        .getDefaultTableColumns(modelResource);
you get all columns defined for Organization entity in the default table.

Using
12    String modelResource = "com.liferay.portal.model.Organization";3    String expandoTableName = ExpandoTableConstants.DEFAULT_TABLE_NAME;4    List<ExpandoRow> expandoRows = ExpandoRowLocalServiceUtil5        .getRows(modelResource, expandoTableName, getStart(), getEnd());
you get all rows for Organization in the default table.

Using
12    String modelResource = "com.liferay.portal.model.Organization";3    String expandoTableName = ExpandoTableConstants.DEFAULT_TABLE_NAME;4    long classPK = 0; // ID OF ORGANIZATION5    List<ExpandoValue> values = ExpandoValueLocalServiceUtil6        .getRowValues(modelResource, expandoTableName, classPK, 7                QueryUtil.ALL_POS, QueryUtil.ALL_POS);
you get all values for Organization with ID 'classPK' in the default table.


1    <liferay-ui:custom-attribute-list2        className="com.liferay.portal.model.Organization"3        classPK="0"4        editable="<%= true %>"5        label="<%= true %>"6    />





如果想让用户注册的时候添加额外的属性可以参照下面的说明:
1.修改expando.xml guest-suport权限
2.以超级管理员的身份修改用户自定义属性增加guest update权限
3.在注册页面上添加新的属性注册字段例(ss)如:
<div class="ctrl-holder">
<liferay-ui:custom-attribute className="<%= User.class.getName() %>" classPK="<%= user2 != null ? user2.getUserId() : 0 %>" editable="<%= true %>"

name="ss" />
4.在com.liferay.portlet.login.action.CreateAccountAction--(portal-impl)
  protected void addUser(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception
  中添加:
   ServiceContext serviceContext = ServiceContextFactory.getInstance(
User.class.getName(), actionRequest);
备注:
    因为:
1.ServiceContextFactory.getInstance(
User.class.getName(), actionRequest);
   这个方法可以得到com.liferay.portal.util.PortalImpl.getExpandoBridgeAttributes(ExpandoBridge, PortletRequest)
   代码:
if (param.indexOf("ExpandoAttributeName(") != -1) {
String name = ParamUtil.getString(portletRequest, param);
names.add(name);
}
   并将actionRequest 中的CustomerAttribute注入到ExpandoBridgeAttributes Map中这样完成了关联。
2.serviceContext.getExpandoBridgeAttributes() 这个方法可以得到对应User.class.getName() 的ExpandoBridge
当保存user 实体对象时候 ExpandoBridge被按属性方式保存 这时候自定义属性会被保存并关联到对应的实体对象上。
[
在我测试的过程中发现一个问题:
使用5.1版本
在页面设置里面添加一个新的页面,填写完名称、html标题,保存页面信息。左边的树上看不到新添加的页面名称,只有一个页面的图标。
页面的名称和标题没有提交到数据库,数据库显示的是<root />。
请问是什么原因?

解决方式:
找到原因了
我把system.properties中
user.country=US
user.language=en
给改成
user.country=CN
user.language=zh_CN
就出现上述问题,改回去就好了

原因:
原因应该是默认的资源文件没找到。在添加页面时,把页面名默认添加到了system.properties制定的语言资源中
]

改好了继续:

添加个页面类似有Control Panel
添加后需要再页面管理中添加应用:)
这样就知道目录结构了
category.hidden 的项目无法添加到普通页面,也许可以修改属性分类就可以了
<category name="category.hidden">
<portlet id="9" />
<portlet id="15" />
<portlet id="25" />
<portlet id="79" />
<portlet id="99" />
<portlet id="104" />
<portlet id="111" />
<portlet id="125" />
<portlet id="126" />
<portlet id="127" />
<portlet id="128" />
<portlet id="129" />
<portlet id="130" />
<portlet id="131" />
<portlet id="132" />
<portlet id="134" />
<portlet id="135" />
<portlet id="136" />
<portlet id="137" />
</category>
liferay-display中

 

通过管理员面板找到用户portlet对应的125

找到配置:

<portlet>
  <portlet-name>125</portlet-name>
  <icon>/html/icons/default.png</icon>
  <struts-path>enterprise_admin_users</struts-path>
  <indexer-class>com.liferay.portlet.enterpriseadmin.util.UserIndexer</indexer-class>
  <portlet-url-class>com.liferay.portal.struts.StrutsActionPortletURL</portlet-url-class>
  <control-panel-entry-category>portal</control-panel-entry-category>
  <control-panel-entry-weight>1.0</control-panel-entry-weight>
  <control-panel-entry-class>com.liferay.portlet.enterpriseadmin.UsersControlPanelEntry</control-panel-entry-class>
  <use-default-template>false</use-default-template>
  <restore-current-view>false</restore-current-view>
  <private-request-attributes>false</private-request-attributes>
  <private-session-attributes>false</private-session-attributes>
  <render-weight>50</render-weight>
  <header-portlet-css>/html/portlet/communities/css.jsp</header-portlet-css>
  <header-portlet-css>/html/portlet/enterprise_admin/css.jsp</header-portlet-css>
  <footer-portlet-javascript>/html/portlet/enterprise_admin/javascript.js</footer-portlet-javascript>
  <css-class-wrapper>portlet-enterprise-admin</css-class-wrapper>
 </portlet>

 

 

点击用户portlet的时候:

enterprise_admin view.jsp

<%
/**
 * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
%>

<%@ include file="/html/portlet/enterprise_admin/init.jsp" %>

<%
String tabs2 = ParamUtil.getString(request, "tabs2");
String tabs3 = ParamUtil.getString(request, "tabs3");

PortletURL portletURL = renderResponse.createRenderURL();

portletURL.setWindowState(WindowState.MAXIMIZED);

portletURL.setParameter("struts_action", "/enterprise_admin/view");
portletURL.setParameter("tabs1", tabs1);
portletURL.setParameter("tabs2", tabs2);
portletURL.setParameter("tabs3", tabs3);

pageContext.setAttribute("portletURL", portletURL);

String portletURLString = portletURL.toString();

request.setAttribute("view.jsp-portletURL", portletURL);
request.setAttribute("view.jsp-portletURLString", portletURLString);
%>

<script type="text/javascript">
 function <portlet:namespace />deleteOrganization(organizationId) {
  <portlet:namespace />doDeleteOrganizationOrUserGroup('<%= Organization.class.getName() %>', organizationId);
 }

 function <portlet:namespace />deleteOrganizations() {
  var organizationIds = Liferay.Util.listCheckedExcept(document.<portlet:namespace />fm, "<portlet:namespace />allRowIds");

  if (!organizationIds) {
   return;
  }

  <portlet:namespace />doDeleteOrganizationOrUserGroup('<%= Organization.class.getName() %>', organizationIds);
 }

 function <portlet:namespace />deleteUserGroup(userGroupId) {
  <portlet:namespace />doDeleteOrganizationOrUserGroup('<%= UserGroup.class.getName() %>', userGroupId);
 }

 function <portlet:namespace />deleteUserGroups() {
  var userGroupIds = Liferay.Util.listCheckedExcept(document.<portlet:namespace />fm, "<portlet:namespace />allRowIds");

  if (!userGroupIds) {
   return;
  }

  <portlet:namespace />doDeleteOrganizationOrUserGroup('<%= UserGroup.class.getName() %>', userGroupIds);
 }

 function <portlet:namespace />deleteUsers(cmd) {
  var deleteUsers = true;

  var deleteUserIds = Liferay.Util.listCheckedExcept(document.<portlet:namespace />fm, "<portlet:namespace />allRowIds");

  if (!deleteUserIds) {
   deleteUsers = false;
  }
  else if (cmd == "<%= Constants.DEACTIVATE %>") {
   if (!confirm('<%= UnicodeLanguageUtil.get(pageContext, "are-you-sure-you-want-to-deactivate-the-selected-users") %>')) {
    deleteUsers = false;
   }
  }
  else if (cmd == "<%= Constants.DELETE %>") {
   if (!confirm('<%= UnicodeLanguageUtil.get(pageContext, "are-you-sure-you-want-to-permanently-delete-the-selected-users") %>')) {
    deleteUsers = false;
   }
  }

  if (deleteUsers) {
   document.<portlet:namespace />fm.method = "post";
   document.<portlet:namespace />fm.<portlet:namespace /><%= Constants.CMD %>.value = cmd;
   document.<portlet:namespace />fm.<portlet:namespace />redirect.value = document.<portlet:namespace />fm.<portlet:namespace />usersRedirect.value;
   document.<portlet:namespace />fm.<portlet:namespace />deleteUserIds.value = deleteUserIds;
   submitForm(document.<portlet:namespace />fm, "<portlet:actionURL windowState="<%= WindowState.MAXIMIZED.toString() %>"><portlet:param name="struts_action" value="/enterprise_admin/edit_user" /></portlet:actionURL>");
  }
 }

 function <portlet:namespace />doDeleteOrganizationOrUserGroup(className, id) {
  var ids = id;

  <portlet:namespace />getUsersCount(
   className, ids, false,
   function(count) {
    count = parseInt(count);

    if (count > 0) {
     <portlet:namespace />getUsersCount(
      className, ids, true,
      function(count) {
       count = parseInt(count);

       if (count > 0) {
        if (confirm('<%= UnicodeLanguageUtil.get(pageContext, "are-you-sure-you-want-to-delete-this") %>')) {
         <portlet:namespace />doDeleteOrganizations(ids);
        }
       }
       else {
        var message = null;

        if (id && (id.split(",").length > 1)) {
         if (className == '<%= Organization.class.getName() %>') {
          message = '<%= UnicodeLanguageUtil.get(pageContext, "one-or-more-organizations-are-associated-with-deactivated-users.-do-you-want-to-proceed-with-deleting-the-selected-organizations-by-automatically-unassociating-the-deactivated-users") %>';
         }
         else {
          message = '<%= UnicodeLanguageUtil.get(pageContext, "one-or-more-user-groups-are-associated-with-deactivated-users.-do-you-want-to-proceed-with-deleting-the-selected-user-groups-by-automatically-unassociating-the-deactivated-users") %>';
         }
        }
        else {
         if (className == '<%= Organization.class.getName() %>') {
          message = '<%= UnicodeLanguageUtil.get(pageContext, "the-selected-organization-is-associated-with-deactivated-users.-do-you-want-to-proceed-with-deleting-the-selected-organization-by-automatically-unassociating-the-deactivated-users") %>';
         }
         else {
          message = '<%= UnicodeLanguageUtil.get(pageContext, "the-selected-user-group-is-associated-with-deactivated-users.-do-you-want-to-proceed-with-deleting-the-selected-user-group-by-automatically-unassociating-the-deactivated-users") %>';
         }
        }

        if (confirm(message)) {
         if (className == '<%= Organization.class.getName() %>') {
          <portlet:namespace />doDeleteOrganizations(ids);
         }
         else {
          <portlet:namespace />doDeleteUserGroups(ids);
         }
        }
       }
      }
     );
    }
    else {
     if (confirm('<%= UnicodeLanguageUtil.get(pageContext, "are-you-sure-you-want-to-delete-this") %>')) {
      if (className == '<%= Organization.class.getName() %>') {
       <portlet:namespace />doDeleteOrganizations(ids);
      }
      else {
       <portlet:namespace />doDeleteUserGroups(ids);
      }
     }
    }
   }
  );
 }

 function <portlet:namespace />doDeleteOrganizations(organizationIds) {
  document.<portlet:namespace />fm.method = "post";
  document.<portlet:namespace />fm.<portlet:namespace /><%= Constants.CMD %>.value = "<%= Constants.DELETE %>";
  document.<portlet:namespace />fm.<portlet:namespace />redirect.value = document.<portlet:namespace />fm.<portlet:namespace />organizationsRedirect.value;
  document.<portlet:namespace />fm.<portlet:namespace />deleteOrganizationIds.value = organizationIds;
  submitForm(document.<portlet:namespace />fm, "<portlet:actionURL windowState="<%= WindowState.MAXIMIZED.toString() %>"><portlet:param name="struts_action" value="/enterprise_admin/edit_organization" /></portlet:actionURL>");
 }

 function <portlet:namespace />doDeleteUserGroups(userGroupIds) {
  document.<portlet:namespace />fm.method = "post";
  document.<portlet:namespace />fm.<portlet:namespace /><%= Constants.CMD %>.value = "<%= Constants.DELETE %>";
  document.<portlet:namespace />fm.<portlet:namespace />redirect.value = document.<portlet:namespace />fm.<portlet:namespace />userGroupsRedirect.value;
  document.<portlet:namespace />fm.<portlet:namespace />deleteUserGroupIds.value = userGroupIds;
  submitForm(document.<portlet:namespace />fm, "<portlet:actionURL windowState="<%= WindowState.MAXIMIZED.toString() %>"><portlet:param name="struts_action" value="/enterprise_admin/edit_user_group" /></portlet:actionURL>");
 }

 function <portlet:namespace />getUsersCount(className, ids, active, callback) {
  jQuery.ajax(
   {
    url: '<%= themeDisplay.getPathMain() %>/enterprise_admin/get_users_count',
    data: {
     className: className,
     ids: ids,
     active: active
    },
    success: callback
   }
  );
 }

 function <portlet:namespace />saveCompany() {
  document.<portlet:namespace />fm.method = "post";
  document.<portlet:namespace />fm.<portlet:namespace /><%= Constants.CMD %>.value = "<%= Constants.UPDATE %>";
  document.<portlet:namespace />fm.<portlet:namespace />redirect.value = "<portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>"><portlet:param name="struts_action" value="/enterprise_admin/view" /><portlet:param name="tabs1" value="<%= tabs1 %>" /><portlet:param name="tabs2" value="<%= tabs2 %>" /><portlet:param name="tabs3" value="<%= tabs3 %>" /></portlet:renderURL>";

  <portlet:namespace />saveLdap();
  <portlet:namespace />saveEmails();

  submitForm(document.<portlet:namespace />fm, "<portlet:actionURL windowState="<%= WindowState.MAXIMIZED.toString() %>"><portlet:param name="struts_action" value="/enterprise_admin/edit_company" /></portlet:actionURL>");
 }
</script>

<form class="uni-form" action="<%= portletURLString %>" method="get" name="<portlet:namespace />fm" onSubmit="submitForm(this); return false;">
<liferay-portlet:renderURLParams varImpl="portletURL" />
<input name="<portlet:namespace /><%= Constants.CMD %>" type="hidden" value="" />
<input name="<portlet:namespace />tabs1" type="hidden" value="<%= HtmlUtil.escape(tabs1) %>" />
<input name="<portlet:namespace />tabs2" type="hidden" value="<%= HtmlUtil.escape(tabs2) %>" />
<input name="<portlet:namespace />tabs3" type="hidden" value="<%= HtmlUtil.escape(tabs3) %>" />
<input name="<portlet:namespace />redirect" type="hidden" value="<%= portletURLString %>" />

<c:if test="<%= showTabs1 %>">
 <liferay-util:include page="/html/portlet/enterprise_admin/tabs1.jsp" />
</c:if>

<c:choose>
 <c:when test='<%= tabs1.equals("users") %>'>
  <liferay-util:include page="/html/portlet/enterprise_admin/view_users.jsp" />
 </c:when>
 <c:when test='<%= tabs1.equals("organizations") %>'>
  <liferay-util:include page="/html/portlet/enterprise_admin/view_organizations.jsp" />
 </c:when>
 <c:when test='<%= tabs1.equals("user-groups") %>'>
  <liferay-util:include page="/html/portlet/enterprise_admin/view_user_groups.jsp" />
 </c:when>
 <c:when test='<%= tabs1.equals("roles") %>'>
  <liferay-util:include page="/html/portlet/enterprise_admin/view_roles.jsp" />
 </c:when>
 <c:when test='<%= tabs1.equals("password-policies") %>'>
  <liferay-util:include page="/html/portlet/enterprise_admin/view_password_policies.jsp" />
 </c:when>
 <c:when test='<%= tabs1.equals("settings") %>'>
  <liferay-util:include page="/html/portlet/enterprise_admin/edit_settings.jsp" />
 </c:when>
 <c:when test='<%= tabs1.equals("monitoring") %>'>
  <liferay-util:include page="/html/portlet/enterprise_admin/view_monitoring.jsp" />
 </c:when>
 <c:when test='<%= tabs1.equals("plugins") %>'>

  <%
  PortletURL installPluginsURL = null;

  boolean showEditPluginHREF = true;
  boolean showReindexButton = false;
  %>

  <%@ include file="/html/portlet/enterprise_admin/plugins.jspf" %>
 </c:when>
</c:choose>

</form>

<%!
private static final long[] _DURATIONS = {300, 600, 1800, 3600, 7200, 10800, 21600};
%>

============================================================

<liferay-util:include page="/html/portlet/enterprise_admin/view_users.jsp" />

 

<%@ include file="/html/portlet/enterprise_admin/init.jsp" %>

<%
PortletURL portletURL = (PortletURL)request.getAttribute("view.jsp-portletURL");

String viewUsersRedirect = ParamUtil.getString(request, "viewUsersRedirect");

if (Validator.isNotNull(viewUsersRedirect)) {
 portletURL.setParameter("viewUsersRedirect", viewUsersRedirect);
}
%>

<liferay-ui:error exception="<%= RequiredUserException.class %>" message="you-cannot-delete-or-deactivate-yourself" />

<liferay-util:include page="/html/portlet/enterprise_admin/user/toolbar.jsp">
 <liferay-util:param name="toolbarItem" value="view-all" />
 <liferay-util:param name="backURL" value="<%= viewUsersRedirect %>" />
</liferay-util:include>

<c:if test="<%= Validator.isNotNull(viewUsersRedirect) %>">
 <input name="<portlet:namespace />viewUsersRedirect" type="hidden" value="<%= HtmlUtil.escape(viewUsersRedirect) %>" />
</c:if>

<liferay-ui:search-container
 rowChecker="<%= new RowChecker(renderResponse) %>"
 searchContainer="<%= new UserSearch(renderRequest, portletURL) %>"
>
 <input name="<portlet:namespace />deleteUserIds" type="hidden" value="" />
 <input name="<portlet:namespace />usersRedirect" type="hidden" value="<%= portletURL.toString() %>" />

 <%
 UserSearchTerms searchTerms = (UserSearchTerms)searchContainer.getSearchTerms();

 if (!searchTerms.isAdvancedSearch() && !searchTerms.hasActive()) {
  searchTerms.setActive(Boolean.TRUE);
 }

 long organizationId = searchTerms.getOrganizationId();
 long roleId = searchTerms.getRoleId();
 long userGroupId = searchTerms.getUserGroupId();

 Organization organization = null;

 if ((organizationId > 0)) {
  try {
   organization = OrganizationLocalServiceUtil.getOrganization(organizationId);
  }
  catch (NoSuchOrganizationException nsoe) {
  }
 }

 Role role = null;

 if (roleId > 0) {
  try {
   role = RoleLocalServiceUtil.getRole(roleId);
  }
  catch (NoSuchRoleException nsre) {
  }
 }

 UserGroup userGroup = null;

 if (userGroupId > 0) {
  try {
   userGroup = UserGroupLocalServiceUtil.getUserGroup(userGroupId);
  }
  catch (NoSuchUserGroupException nsuge) {
  }
 }
 %>

 <c:if test="<%= organization != null %>">
  <input name="<portlet:namespace /><%= UserDisplayTerms.ORGANIZATION_ID %>" type="hidden" value="<%= organization.getOrganizationId() %>" />

  <h3><%= LanguageUtil.format(pageContext, "users-of-x", HtmlUtil.escape(organization.getName())) %></h3>
 </c:if>

 <c:if test="<%= role != null %>">
  <input name="<portlet:namespace /><%= UserDisplayTerms.ROLE_ID %>" type="hidden" value="<%= role.getRoleId() %>" />

  <h3><%= LanguageUtil.format(pageContext, "users-with-role-x", HtmlUtil.escape(role.getTitle(locale))) %></h3>
 </c:if>

 <c:if test="<%= userGroup != null %>">
  <input name="<portlet:namespace /><%= UserDisplayTerms.USER_GROUP_ID %>" type="hidden" value="<%= userGroup.getUserGroupId() %>" />

  <h3><%= LanguageUtil.format(pageContext, "users-of-x", HtmlUtil.escape(userGroup.getName())) %></h3>
 </c:if>

 <liferay-ui:search-form
  page="/html/portlet/enterprise_admin/user_search.jsp"
 />

 <c:if test="<%= windowState.equals(WindowState.MAXIMIZED) %>">

  <%
  LinkedHashMap userParams = new LinkedHashMap();

  if (organizationId > 0) {
   userParams.put("usersOrgs", new Long(organizationId));
  }
  else {
   if (filterManageableOrganizations) {
    Long[] organizationIds = EnterpriseAdminUtil.getOrganizationIds(user.getOrganizations());

    userParams.put("usersOrgs", organizationIds);
   }
  }

  if (roleId > 0) {
   userParams.put("usersRoles", new Long(roleId));
  }

  if (userGroupId > 0) {
   userParams.put("usersUserGroups", new Long(userGroupId));
  }
  %>

  <liferay-ui:search-container-results>
   <%@ include file="/html/portlet/enterprise_admin/user_search_results_index.jspf" %>
  </liferay-ui:search-container-results>

  <liferay-ui:search-container-row
   className="com.liferay.portal.model.User"
   escapedModel="<%= true %>"
   keyProperty="userId"
   modelVar="user2"
  >
   <liferay-portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>" varImpl="rowURL">
    <portlet:param name="struts_action" value="/enterprise_admin/edit_user" />
    <portlet:param name="redirect" value="<%= searchContainer.getIteratorURL().toString() %>" />
    <portlet:param name="p_u_i_d" value="<%= String.valueOf(user2.getUserId()) %>" />
   </liferay-portlet:renderURL>

   <%@ include file="/html/portlet/enterprise_admin/user/search_columns.jspf" %>

   <liferay-ui:search-container-column-jsp
    align="right"
    path="/html/portlet/enterprise_admin/user_action.jsp"
   />
  </liferay-ui:search-container-row>

  <div class="separator"><!-- --></div>

  <%
  boolean hasButtons = false;
  %>

  <c:if test="<%= searchTerms.hasActive() && (searchTerms.isActive() || (!searchTerms.isActive() && PropsValues.USERS_DELETE)) %>">

   <%
   hasButtons = true;
   %>

   <input type="button" value='<%= LanguageUtil.get(pageContext, (searchTerms.isActive() ? Constants.DEACTIVATE : Constants.DELETE)) %>' onClick="<portlet:namespace />deleteUsers('<%= searchTerms.isActive() ? Constants.DEACTIVATE : Constants.DELETE %>');" />
  </c:if>

  <c:if test="<%= searchTerms.hasActive() && !searchTerms.isActive() %>">

   <%
   hasButtons = true;
   %>

   <input type="button" value="<liferay-ui:message key="restore" />" onClick="<portlet:namespace />deleteUsers('<%= Constants.RESTORE %>');" />
  </c:if>

  <c:if test="<%= hasButtons %>">
   <div>
    <br />
   </div>
  </c:if>

  <%
  if (!hasButtons) {
   searchContainer.setRowChecker(null);
  }
  %>

  <liferay-ui:search-iterator />
 </c:if>
</liferay-ui:search-container>

 

 

 

对应的用户页面是enterprise_admin下的user 下的toolbar.jsp

 

<%@ include file="/html/portlet/enterprise_admin/init.jsp" %>

<%
String toolbarItem = ParamUtil.getString(request, "toolbarItem", "view-all");
String backURL = ParamUtil.getString(request, "backURL");
%>

<div class="lfr-portlet-toolbar">
 <portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>" var="viewUsersURL">
  <portlet:param name="struts_action" value="/enterprise_admin/view" />
 </portlet:renderURL>

 <span class="lfr-toolbar-button view-button <%= toolbarItem.equals("view-all") ? "current" : StringPool.BLANK %>">
  <a href="<%= viewUsersURL %>"><liferay-ui:message key="view-all" /></a>
 </span>

 <c:if test="<%= PortalPermissionUtil.contains(permissionChecker, ActionKeys.ADD_USER) %>">
  <portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>" var="addUserURL">
   <portlet:param name="struts_action" value="/enterprise_admin/edit_user" />
   <portlet:param name="redirect" value="<%= currentURL %>" />
  </portlet:renderURL>

  <span class="lfr-toolbar-button add-button <%= toolbarItem.equals("add") ? "current" : StringPool.BLANK %>"><a href="<%= addUserURL %>"><liferay-ui:message key="add" /></a></span>
 </c:if>


 <c:if test="<%= RoleLocalServiceUtil.hasUserRole(user.getUserId(), user.getCompanyId(), RoleConstants.ADMINISTRATOR, true) %>">
  <liferay-portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>" var="expandoURL" portletName="<%= PortletKeys.EXPANDO %>">
   <portlet:param name="struts_action" value="/expando/view" />
   <portlet:param name="redirect" value="<%= currentURL %>" />
   <portlet:param name="modelResource" value="<%= User.class.getName() %>" />
  </liferay-portlet:renderURL>

  <span class="lfr-toolbar-button custom-attributes-button"><a href="<%= expandoURL %>"><liferay-ui:message key="custom-attributes" /></a></span>

  <span class="lfr-toolbar-button export-button"><a href="javascript: submitForm(document.hrefFm, '<%= themeDisplay.getPathMain() %>/enterprise_admin/export_users');"><liferay-ui:message key="export" /></a></span>
 </c:if>

 <c:if test="<%= Validator.isNotNull(backURL) %>">
  <span class="lfr-toolbar-button back-button">
   <a href="<%= HtmlUtil.escape(backURL) %>">&laquo; <liferay-ui:message key="back" /></a>
  </span>
 </c:if>
</div>

====================================================================

找到expando portlet的view.jsp

<%
String redirect = ParamUtil.getString(request, "redirect");

String modelResource = ParamUtil.getString(request, "modelResource");
String modelResourceName = ResourceActionsUtil.getModelResource(pageContext, modelResource);

PortletURL portletURL = renderResponse.createRenderURL();

portletURL.setParameter("struts_action", "/expando/view");
portletURL.setParameter("redirect", redirect);
portletURL.setParameter("modelResource", modelResource);
%>

备注:

PortletURL portletURL = renderResponse.createRenderURL();的结果是这样的

http://localhost:8080/group/control_panel/manage?

p_p_id=139&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view

&doAsGroupId=10137&refererPlid=10140&

_139_struts_action=%2Fexpando%2Fview&

_139_redirect=%2Fgroup%2Fcontrol_panel%2Fmanage%3Fp_p_id%3D125%26p_p_lifecycle%3D0%26p_p_state%3Dmaximized%26p_p_mode%3Dview%26doAsGroupId%3D10137%26refererPlid%3D10140&_139_modelResource=com.liferay.portal.model.User

是一个完整的页面路径

 

<portlet:namespace /> 的结果为_139_

 

<script type="text/javascript">  function <portlet:namespace />addExpando() {   submitForm(document.hrefFm, '<portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>"><portlet:param name="struts_action" value="/expando/edit_expando" /><portlet:param name="redirect" value="<%= currentURL %>" /><portlet:param name="modelResource" value="<%= modelResource %>" /></portlet:renderURL>');  } </script>

形成的代码为

<script type="text/javascript">

/*<![CDATA[*/

function

_139_addExpando()

{

submitForm(document.hrefFm,

"http://localhost:8080/group/control_panel/manage?p_p_id=139&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&doAsGroupId=10137&refererPlid=10140&_139_struts_action=%2Fexpando%2Fedit_expando&_139_redirect=%2Fgroup%2Fcontrol_panel%2Fmanage%3Fp_p_id%3D139%26p_p_lifecycle%3D0%26p_p_state%3Dmaximized%26p_p_mode%3Dview%26doAsGroupId%3D10137%26refererPlid%3D10140%26_139_struts_action%3D%252Fexpando%252Fview%26_139_redirect%3D%252Fgroup%252Fcontrol_panel%252Fmanage%253Fp_p_id%253D125%2526p_p_lifecycle%253D0%2526p_p_state%253Dmaximized%2526p_p_mode%253Dview%2526doAsGroupId%253D10137%2526refererPlid%253D10140%26_139_modelResource%3Dcom.liferay.portal.model.User&_139_modelResource=com.liferay.portal.model.User")

};

/*]]>*/

</script>

 

<script type="text/javascript">
 function <portlet:namespace />addExpando() {
  submitForm(document.hrefFm, '<portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>"><portlet:param name="struts_action" value="/expando/edit_expando" /><portlet:param name="redirect" value="<%= currentURL %>" /><portlet:param name="modelResource" value="<%= modelResource %>" /></portlet:renderURL>');
 }
</script>

<div>
 <liferay-ui:message key="edit-custom-attributes-for" />: <a href="<%= HtmlUtil.escape(redirect) %>"><%= modelResourceName %></a>
</div>

<br />

<liferay-ui:tabs
 names="custom-attributes"
 backURL="<%= redirect %>"
/>

<%
ExpandoBridge expandoBridge = new ExpandoBridgeImpl(modelResource);

List<String> attributeNames = Collections.list(expandoBridge.getAttributeNames());
%>

<liferay-ui:search-container
 emptyResultsMessage='<%= LanguageUtil.format(pageContext, "no-custom-attributes-are-defined-for-x", modelResourceName) %>'
 iteratorURL="<%= portletURL %>"
>
 <liferay-ui:search-container-results
  total="<%= attributeNames.size() %>"
  results="<%= attributeNames %>"
 />

 <liferay-ui:search-container-row
  className="java.lang.String"
  modelVar="name"
  stringKey="<%= true %>"
 >

  <%
  int type = expandoBridge.getAttributeType(name);

  ExpandoColumn expandoColumn = ExpandoColumnLocalServiceUtil.getDefaultTableColumn(modelResource, name);
  %>

  <portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>" var="rowURL">
   <portlet:param name="struts_action" value="/expando/edit_expando" />
   <portlet:param name="redirect" value="<%= currentURL %>" />
   <portlet:param name="columnId" value="<%= String.valueOf(expandoColumn.getColumnId()) %>" />
   <portlet:param name="modelResource" value="<%= modelResource %>" />
  </portlet:renderURL>

  <liferay-ui:search-container-row-parameter
   name="expandoColumn"
   value="<%= expandoColumn %>"
  />

  <liferay-ui:search-container-row-parameter
   name="modelResource"
   value="<%= modelResource %>"
  />

  <liferay-ui:search-container-column-text
   href="<%= rowURL %>"
   buffer="buffer"
   name="name"
  >

   <%
   String localizedName = LanguageUtil.get(pageContext, name);

   if (name.equals(localizedName)) {
    localizedName = TextFormatter.format(name, TextFormatter.J);
   }

   buffer.append(HtmlUtil.escape(localizedName));
   %>

  </liferay-ui:search-container-column-text>

  <liferay-ui:search-container-column-text
   href="<%= rowURL %>"
   name="key"
   value="<%= HtmlUtil.escape(name) %>"
  />

  <liferay-ui:search-container-column-text
   href="<%= rowURL %>"
   name="type"
   value="<%= LanguageUtil.get(pageContext, ExpandoColumnConstants.getTypeLabel(type)) %>"
  />

  <liferay-ui:search-container-column-text
   buffer="buffer"
   href="<%= rowURL %>"
   name="default-value"
  >

   <%
   if (type == ExpandoColumnConstants.BOOLEAN) {
    buffer.append((Boolean)expandoBridge.getAttributeDefault(name));
   }
   else if (type == ExpandoColumnConstants.BOOLEAN_ARRAY) {
    buffer.append(StringUtil.merge((boolean[])expandoBridge.getAttributeDefault(name), StringPool.COMMA_AND_SPACE));
   }
   else if (type == ExpandoColumnConstants.DATE) {
    buffer.append(dateFormatDateTime.format((Date)expandoBridge.getAttributeDefault(name)));
   }
   else if (type == ExpandoColumnConstants.DATE_ARRAY) {
    Date[] dates = (Date[])expandoBridge.getAttributeDefault(name);

    for (int i = 0; i < dates.length; i++) {
     if (i != 0) {
      buffer.append(StringPool.COMMA_AND_SPACE);
     }

     buffer.append(dateFormatDateTime.format(dates[i]));
    }
   }
   else if (type == ExpandoColumnConstants.DOUBLE) {
    buffer.append((Double)expandoBridge.getAttributeDefault(name));
   }
   else if (type == ExpandoColumnConstants.DOUBLE_ARRAY) {
    buffer.append(StringUtil.merge((double[])expandoBridge.getAttributeDefault(name), StringPool.COMMA_AND_SPACE));
   }
   else if (type == ExpandoColumnConstants.FLOAT) {
    buffer.append((Float)expandoBridge.getAttributeDefault(name));
   }
   else if (type == ExpandoColumnConstants.FLOAT_ARRAY) {
    buffer.append(StringUtil.merge((float[])expandoBridge.getAttributeDefault(name), StringPool.COMMA_AND_SPACE));
   }
   else if (type == ExpandoColumnConstants.INTEGER) {
    buffer.append((Integer)expandoBridge.getAttributeDefault(name));
   }
   else if (type == ExpandoColumnConstants.INTEGER_ARRAY) {
    buffer.append(StringUtil.merge((int[])expandoBridge.getAttributeDefault(name), StringPool.COMMA_AND_SPACE));
   }
   else if (type == ExpandoColumnConstants.LONG) {
    buffer.append((Long)expandoBridge.getAttributeDefault(name));
   }
   else if (type == ExpandoColumnConstants.LONG_ARRAY) {
    buffer.append(StringUtil.merge((long[])expandoBridge.getAttributeDefault(name), StringPool.COMMA_AND_SPACE));
   }
   else if (type == ExpandoColumnConstants.SHORT) {
    buffer.append((Short)expandoBridge.getAttributeDefault(name));
   }
   else if (type == ExpandoColumnConstants.SHORT_ARRAY) {
    buffer.append(StringUtil.merge((short[])expandoBridge.getAttributeDefault(name), StringPool.COMMA_AND_SPACE));
   }
   else if (type == ExpandoColumnConstants.STRING_ARRAY) {
    buffer.append(HtmlUtil.escape(StringUtil.merge((String[])expandoBridge.getAttributeDefault(name), StringPool.COMMA_AND_SPACE)));
   }
   else {
    buffer.append(HtmlUtil.escape((String)expandoBridge.getAttributeDefault(name)));
   }
   %>

  </liferay-ui:search-container-column-text>

  <liferay-ui:search-container-column-jsp
   align="right"
   path="/html/portlet/expando/expando_action.jsp"
  />
 </liferay-ui:search-container-row>

 <c:if test="<%= PortalPermissionUtil.contains(permissionChecker, ActionKeys.ADD_EXPANDO) %>">
  <div>

权限 哈哈):

permissionChecker 来自:

com.liferay.taglib.theme.DefineObjectsTag 视乎有jsp隐式对象的效果,有待检核。。。。。

<liferay-theme:defineObjects /> 

ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
   WebKeys.THEME_DISPLAY);     “THEME_DISPLAY”

分别取出下面的元素:

pageContext.setAttribute(
    "permissionChecker", themeDisplay.getPermissionChecker());

 

themeDisplay

  Pages are rendered via the following mechanism:

 

  1. Request comes in through MainServlet. Various attributes are stored in the session and request. The request attribute WebKeys.CURRENT_URL holds the currently requested path (stripped of protocol,host, and port)
  2. The "service pre action" handler com.liferay.portal.events.ServicePreAction is called, where the layout and theme to display are determined. The current layout is stored as a request attribute under the key WebKeys.LAYOUT. The other available layouts are stored as a request attribute under the key WebKeys.LAYOUTS. The theme to display is stored as a request attribute under the WebKeys.THEME key, and the color scheme to use is stored as the request attribute WebKeys.COLOR_SCHEME. The theme and color scheme are usually determined by querying the layout once it has been determined.
  3. Struts is called to handle the request, and Liferay uses the custom Struts request processor com.liferay.portal.struts.PortalRequestProcessor. The PortalRequestProcessor.getLastPath() method computes the last path visited, and supplies a default path for the first entry into the portal. The default path upon entry into the portal is <protocol>://<hostName>:<port>/portal/layout. This url may optionally contain the query parameters ?p_l_id=default if the user is known (i.e. they have just logged in).
  4. This initial request for /portal/layout is handled by com.liferay.portal.action.LayoutAction.
  5. /html/common/themes/portal.jsp is the "top level" display page. It selects...
  6. the portal_normal.jsp or portal_pop_up.jsp based on the current state of the theme's display, and includes it using the <liferay-theme:include> custom tag, implemented by com.liferay.taglib.theme.IncludeTag, which in turn calls com.liferay.taglib.util.ThemeUtil.include().
  7. Eventually, for each portlet, the method com.liferay.portal.util.PortalUtil.renderPortlet() gets called, which calls
  8. /portal/portal-web/docroot/html/portal/render_portlet.jsp to render the contents of an individual portlet. That in turn calls
  9. /portal/portal-web/docroot/html/common/themes/portlet.jsp, which ends up calling
  10. /portal/portal-web/docroot/html/common/themes/portlet_content.jsp

PortalUtil 得到 Company  getPortal() 起了很大作用

public static Company getCompany(HttpServletRequest request)
  throws PortalException, SystemException {

  return getPortal().getCompany(request);
 }

=================================================================

PortalPermissionUtil.contains(permissionChecker, ActionKeys.ADD_EXPANDO)

 

 

ResourceActionsUtil 最终最终它

 

themeDisplay - com.liferay.portal.theme.ThemeDisplay
company - com.liferay.portal.model.Company
account - com.liferay.portal.model.Account (deprecated)
user - com.liferay.portal.model.User
realUser - com.liferay.portal.model.User
contact - com.liferay.portal.model.Contact
layout - com.liferay.portal.model.Layout
layouts - List<com.liferay.portal.model.Layout>
plid - java.lang.Long
layoutTypePortlet - com.liferay.portal.model.LayoutTypePortlet
portletGroupId - java.lang.Long
permissionChecker - com.liferay.portal.security.permission.PermissionChecker
locale - java.util.Locale
timeZone - java.util.TimeZone
theme - com.liferay.portal.model.Theme
colorScheme - com.liferay.portal.model.ColorScheme
portletDisplay - com.liferay.portal.theme.PortletDisplay

这样就不奇怪了

   <input type="button" value="<liferay-ui:message key="add-custom-attribute" />" onClick="<portlet:namespace />addExpando();" />
  </div>

  <br />
 </c:if>

 <liferay-ui:search-iterator paginate="<%= false %>" />
</liferay-ui:search-container>

 

看里面代码就能明白expando的执行过程了

经行中。。。。

 

  • 大小: 38.6 KB
分享到:
评论
2 楼 liuzhifeixff 2010-10-27  
乱七八糟的./././././
1 楼 ww_java 2010-07-29  
不知你是怎么弄来的代码,,一句话,无法阅读.太混乱

相关推荐

    liferay学习系列文章

    2. **Portlet开发**:介绍portlet生命周期,MVC Portlet的工作原理,以及如何使用Liferay的开发工具创建和调试portlet。 3. **主题与布局**:Liferay的主题决定了门户的外观,而布局决定了页面元素的排布。如何...

    liferay快速入门quickstart

    - **Liferay SDK:**Liferay提供了SDK,包含了一系列工具和模板,帮助开发者快速构建和部署Portlets。 - **编写简单JSPPortlet:**通过学习如何编写JSPPortlet,开发者能够理解Liferay Portlet的基本结构和工作原理...

    liferay-portal-sql-6.1.1-ce-ga2-20120731132656558

    1. **安装脚本**:通常在安装或更新Liferay Portal时,会有一系列的SQL脚本用于创建必要的数据库结构,包括表、视图、存储过程等。 2. **升级脚本**:随着Liferay版本的升级,这些脚本可能用于将现有数据库从一个...

    liferay开发文档集合

    《Liferay开发文档集合》是针对企业级门户平台Liferay的一系列技术指南,涵盖了从基础安装到高级定制的全方位知识。这些PDF文档旨在帮助开发者、系统管理员和IT专业人员更好地理解和利用Liferay Portal来构建和管理...

    Liferay_学习笔记

    【Liferay 学习笔记】 Liferay 是一款开源的企业级门户平台,用于构建和管理复杂的Web应用程序。在本文中,我们将深入探讨如何在Liferay中进行一些基本操作和配置,如修改公司LOGO、增加用户、创建页面以及理解...

    LIFERAY学习资料

    2. **Liferay架构**: Liferay的架构基于模型-视图-控制器(MVC)模式,采用服务导向架构(SOA),支持portlet容器、工作流引擎、搜索引擎和社交网络功能。它利用Spring框架进行依赖注入,并使用Hibernate作为持久...

    liferay portal开发大全

    本资源集是针对Liferay Portal开发的一系列中文文档,旨在帮助开发者全面了解和掌握Liferay的相关技术。 1. **Liferay Portal 架构** Liferay Portal的核心架构基于Java EE标准,包括Servlet容器、EJB、JMS和JPA等...

    Liferay系列文章 7章 从介绍 到入门

    【Liferay 系列文章 7章 从介绍 到入门】 Liferay 是一款开源的企业级门户平台,本文将...通过学习这一系列文章,读者不仅可以理解Portal技术的重要性,还能具备实际操作Liferay的能力,以应对现代企业信息化的需求。

    Liferay_6.1开发学习

    Liferay 6.1 是在2011年发布的版本,引入了一系列重要的新特性,如文件同步功能,增强了文档库的管理,优化了用户界面,提供了表单和工作流设计器,以及对移动设备的更好支持。这一版本的发布进一步提升了Liferay的...

    liferay portal 开发指南

    ### Liferay Portal 开发指南知识点概述 ...通过学习本文档,开发者不仅可以掌握 Portlet 的开发技巧,还能深入了解 Liferay Portal 的架构和技术特点,从而更好地利用该平台来满足企业的业务需求。

    liferay portlet demo

    2. **Portlet**:Portlet是Liferay中的核心组件,它们类似于小型的Web应用,可以嵌入到门户页面中,提供各种功能,如新闻显示、日历管理、搜索等。 3. **portlet生命周期**:包括初始化、加载、渲染、动作处理和...

    liferay如何在eclipse中配置开发和debug环境

    为了在Eclipse环境中高效地开发和调试Liferay应用,我们需要进行一系列的配置步骤。以下将详细介绍如何在Eclipse中设置Liferay的开发和Debug环境。 1. **安装必要的软件和插件** - 首先,确保你已经安装了最新版本...

    liferay in action.pdf

    ### Liferay in Action – 关键知识点解析 #### 一、概览 《Liferay in Action》是一本关于Liferay Portal开发的官方...通过学习本书,您可以掌握如何利用Liferay构建复杂的企业级应用,提高工作效率并降低维护成本。

    liferay 6.0.5 api

    通过详细阅读这个文档,开发者可以学习如何有效地利用Liferay API进行开发,提高工作效率,同时确保与Liferay 6.0.5版本的兼容性。 总之,Liferay 6.0.5 API 是开发者深入挖掘Liferay潜力、定制化企业级解决方案的...

    Liferay 使用手册

    此外,Liferay 提供了一系列的命令行工具,如Liferay CLI,用于自动化部署和管理任务。 在实际操作中,Liferay 的安装和配置可能会涉及到多个层面,包括数据库连接、服务器设置、安全策略等。手册通常会详细解释...

    liferay6.2 CRUD FriendlyURL Search-Container

    Liferay 6.2 是一个流行的开源企业级门户平台,它提供了一系列强大的功能,包括内容管理、社交协作、用户管理等。在这个“liferay6.2 CRUD FriendlyURL Search-Container”示例中,我们将深入探讨如何在Liferay 6.2...

    liferay相关文档

    Liferay提供了一系列的社交协作功能,如社交网络、社区论坛、即时通讯、日程管理、任务分配等,帮助企业构建内部社交环境,提升团队协作效率。 8. **内容管理和文档库** Liferay的内容管理系统支持文档的上传、...

    liferay的主题

    1. **主题结构**:Liferay主题通常包含一系列配置文件和模板文件。在提供的文件名列表中,我们看到了如`build.properties`、`build-common-plugin.xml`等,这些都是构建主题过程中的配置文件。`themes`目录则可能...

Global site tag (gtag.js) - Google Analytics