`
billy_zh
  • 浏览: 61580 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

liferay中portlet action的处理流程

阅读更多

本文用一个实例来说明liferay中portlet action的处理流程.

在liferay的演示网站上随便输入用户名/密码提交后,就可以如下的一个url.
 http://demo.liferay.net/c/portal/layout?p_l_id=PUB.1001.1
  &p_p_id=58
  &p_p_action=1
  &p_p_state=normal
  &p_p_mode=view
  &p_p_col_id=column-1
  &p_p_col_pos=0
  &p_p_col_count=1
  &_58_struts_action=%2Flogin%2Fview
  &_58_cmd=update
  &#p_58

在liferay中,是用struts来做FrontController的,
 〈action path="/portal/layout" type="com.liferay.portal.action.LayoutAction"〉
   〈forward name="portal.layout" path="portal.layout" /〉
 〈/action〉

LayoutAction

 LayoutAction.execute(ActionMapping mapping, ActionForm form,
 HttpServletRequest req, HttpServletResponse res)
  throws Exception {

   String plid = ParamUtil.getString(req, "p_l_id");
   String action = ParamUtil.getString(req, "p_p_action");

   if (Validator.isNotNull(plid)) {
      try {
         if (action.equals("1")) { // 处理action请求.
            _processActionRequest(req, res);

            ActionResponseImpl actionResponseImpl =
                  (ActionResponseImpl)req.getAttribute(WebKeys.JAVAX_PORTLET_RESPONSE);
            String redirectLocation = actionResponseImpl.getRedirectLocation();

            if (Validator.isNotNull(redirectLocation)) {
               res.sendRedirect(redirectLocation);
               return null;
            }

            if (LiferayWindowState.isExclusive(req)) {
               return null;
            }
         }
         else if (action.equals("0")) { // 处理render请求.
            _processRenderRequest(req, res);
         }
         return mapping.findForward("portal.layout");
      } catch (Exception e) {
         req.setAttribute(PageContext.EXCEPTION, e);
         return mapping.findForward(Constants.COMMON_ERROR);
      } finally {
         // 清理工作。
      }
   } else {
      try {
         _forwardLayout(req);
         return mapping.findForward(Constants.COMMON_FORWARD);
      } catch (Exception e) {
         req.setAttribute(PageContext.EXCEPTION, e);
         return mapping.findForward(Constants.COMMON_ERROR);
      }
   }
 }

 Layout._processPortletRequest(
    HttpServletRequest req, HttpServletResponse res, boolean action)
      throws Exception {

      HttpSession ses = req.getSession();

      // 查找portlet.
      String companyId = PortalUtil.getCompanyId(req);
      User user = PortalUtil.getUser(req);
      Layout layout = (Layout)req.getAttribute(WebKeys.LAYOUT);
      String portletId = ParamUtil.getString(req, "p_p_id");

      Portlet portlet = PortletLocalServiceUtil.getPortletById(
   companyId, portletId);

      ServletContext ctx = (ServletContext)req.getAttribute(WebKeys.CTX);

      CachePortlet cachePortlet = PortletInstanceFactory.create(portlet, ctx);

      if (user != null) {
         CachePortlet.clearResponse(ses, layout.getPrimaryKey(), portletId);
      }

      PortletPreferencesPK prefsPK =
         PortletPreferencesFactory.getPortletPreferencesPK(req, portletId);

      PortletPreferences prefs =
         PortletPreferencesLocalServiceUtil.getPreferences(companyId, prefsPK);

      // portlet配置及上下文.
      PortletConfig portletConfig = PortletConfigFactory.create(portlet, ctx);
      PortletContext portletCtx = portletConfig.getPortletContext();

      // window状态.
      WindowState windowState = new WindowState(ParamUtil.getString(req, "p_p_state"));
      // portlet模式.
      PortletMode portletMode = new PortletMode(ParamUtil.getString(req, "p_p_mode"));

      if (action) {  // 处理action.
         ActionRequestImpl actionRequestImpl = ActionRequestFactory.create(
            req, portlet, cachePortlet, portletCtx, windowState,
            portletMode, prefs, layout.getPlid());

         ActionResponseImpl actionResponseImpl =
            ActionResponseFactory.create(
               actionRequestImpl, res, portletId, user, layout,
               windowState, portletMode);

         actionRequestImpl.defineObjects(portletConfig, actionResponseImpl);

         cachePortlet.processAction(actionRequestImpl, actionResponseImpl);

         RenderParametersPool.put(req, layout.getPlid(), portletId,
            actionResponseImpl.getRenderParameters());
      } else { // 处理render.
         PortalUtil.updateWindowState(portletId, user, layout, windowState, req);
         PortalUtil.updatePortletMode(portletId, user, layout, portletMode);
      }
   }
   CachePortlet对普通Portlet进行了包装,加入了cache处理,

CachePortlet

 CachePortlet.processAction(ActionRequest req, ActionResponse res)
  throws IOException, PortletException {
       _invoke(req, res, true);
    }

 CachePortlet._invoke(
      PortletRequest req, PortletResponse res, boolean action)
         throws IOException, PortletException {

      Map properties = null;

      if (_portletConfig.isWARFile()) { // 如果Portlet是外部war整合方式的,则转发请求.
         String path = StringPool.SLASH + _portletConfig.getPortletName() + "/invoke";

         RequestDispatcher rd = _portletCtx.getServletContext().getRequestDispatcher(path);

         HttpServletRequest httpReq = null;
         HttpServletResponse httpRes = null;

         ActionRequestImpl actionReqImpl = null;
         ActionResponseImpl actionResImpl = null;
     
         RenderRequestImpl renderReqImpl = null;
         RenderResponseImpl renderResImpl = null;

         if (action) {
            actionReqImpl = (ActionRequestImpl)req;
            actionResImpl = (ActionResponseImpl)res;

            httpReq = actionReqImpl.getHttpServletRequest();
            httpRes = actionResImpl.getHttpServletResponse();
         } else {
            renderReqImpl = (RenderRequestImpl)req;
            renderResImpl = (RenderResponseImpl)res;

            httpReq = renderReqImpl.getHttpServletRequest();
            httpRes = renderResImpl.getHttpServletResponse();
         }

         httpReq.setAttribute(WebKeys.JAVAX_PORTLET_PORTLET, _portlet);

         try {
            rd.include(httpReq, httpRes);
         } catch (ServletException se) {
            // 重新抛出异常.
         }

         if (action) {
            properties = actionResImpl.getProperties();
         } else {
            properties = renderResImpl.getProperties();
         }
      } else { // Portlet是liferay内部整合方式的,直接交由_portlet处理。
         if (action) {
            ActionRequestImpl actionReqImpl = (ActionRequestImpl)req;
            ActionResponseImpl actionResImpl = (ActionResponseImpl)res;

            _portlet.processAction(actionReqImpl, actionResImpl);

            properties = actionResImpl.getProperties();
         } else {
            RenderRequestImpl renderReqImpl = (RenderRequestImpl)req;
            RenderResponseImpl renderResImpl = (RenderResponseImpl)res;

            _portlet.render(renderReqImpl, renderResImpl);

            properties = renderResImpl.getProperties();
         }
      }

      if ((properties != null) && (properties.size() > 0)) {
         if (_expCache != null) {
            String[] expCache = (String[])properties.get(RenderResponse.EXPIRATION_CACHE);
            if ((expCache != null) && (expCache.length > 0) && (expCache[0] != null)) {
               _expCache = new Integer(GetterUtil.getInteger(expCache[0]));
            }
         }
      }
   }
   在这里,Login portlet是liferay内部整合方式的,
   通过portlet.xml文件和它的portletId,找到它的实现类是StrutsPortlet.

StrutsPortlet

 StrutsPortlet.processAction(ActionRequest req, ActionResponse res)
      throws IOException, PortletException {

   String path = req.getParameter("struts_action"); // 这里为/login/view
   if (Validator.isNotNull(path)) {
      // Call processAction of com.liferay.portal.struts.PortletAction
      PermissionChecker checker = PermissionThreadLocal.getPermissionChecker();
      try {
         checker.setValues(req);
         // Process action
         PortletRequestProcessor processor = _getPortletRequestProcessor(req);
         processor.process(req, res, path);
      } catch (ServletException se) {
         throw new PortletException(se);
      } finally {
         checker.resetValues();
      }
   }
   if (copyRequestParameters) {
      PortalUtil.copyRequestParameters(req, res);
   }
 }

 // /login/view定义.
  〈action path="/login/view" type="com.liferay.portlet.login.action.ViewAction"〉
     〈forward name="portlet.login.view" path="portlet.login.view" /〉
  〈/action〉

PortletRequestProcessor

 PortletRequestProcessor.process(ActionRequest req, ActionResponse res, String path)
  throws IOException, ServletException {

   ActionRequestImpl reqImpl = (ActionRequestImpl)req;
   ActionResponseImpl resImpl = (ActionResponseImpl)res;

   HttpServletRequest httpReq = reqImpl.getHttpServletRequest();
   HttpServletResponse httpRes = resImpl.getHttpServletResponse();

   ActionMapping mapping = processMapping(httpReq, httpRes, path);

   if (mapping == null) {
      return;
   }

   // processRoles处理,略...

   ActionForm form = processActionForm(httpReq, httpRes, mapping);

   processPopulate(httpReq, httpRes, form, mapping);

   if (!processValidateAction(httpReq, httpRes, form, mapping)) {
      return;
   }

   // 构建ViewAction.
   PortletAction action =
      (PortletAction)processActionCreate(httpReq, httpRes, mapping);

   if (action == null) {
      return;
   }

   PortletConfigImpl portletConfig =
      (PortletConfigImpl)req.getAttribute(WebKeys.JAVAX_PORTLET_CONFIG);

   // 处理action.
   try {
      action.processAction(mapping, form, portletConfig, req, res);
   }
   catch (Exception e) {
      String exceptionId = WebKeys.PORTLET_STRUTS_EXCEPTION +
         StringPool.PERIOD + portletConfig.getPortletId();

      req.setAttribute(exceptionId, e);
   }

   // 处理forward, 略...

ViewAction

 ViewAction.processAction(
   ActionMapping mapping, ActionForm form, PortletConfig config,
   ActionRequest req, ActionResponse res) throws Exception {

   String cmd = req.getParameter(Constants.CMD); // update

   ThemeDisplay themeDisplay =
      (ThemeDisplay)req.getAttribute(WebKeys.THEME_DISPLAY);

   if (req.getRemoteUser() != null) { // 已经登录,直接redirect.
      res.sendRedirect(themeDisplay.getPathMain());
   }
   else if (Validator.isNotNull(cmd)) {
      try {
         _login(themeDisplay, req, res);  // 登录处理.
      } catch (Exception e) {
         // 异常处理.
      }
   }
 }

 ViewAction._login(
   ThemeDisplay themeDisplay, ActionRequest req, ActionResponse res)
      throws Exception {

      ActionRequestImpl reqImpl = (ActionRequestImpl)req;
      ActionResponseImpl resImpl = (ActionResponseImpl)res;

      HttpServletRequest httpReq = reqImpl.getHttpServletRequest();
      HttpServletResponse httpRes = resImpl.getHttpServletResponse();

      String login = ParamUtil.getString(req, "login");
      String password = ParamUtil.getString(req, "password");
      boolean rememberMe = ParamUtil.getBoolean(req, "rememberMe");

      LoginAction.login(httpReq, httpRes, login, password, rememberMe);

      res.sendRedirect(themeDisplay.getPathMain() + "/portal/protected");
  }

  LoginAction.login的处理这里就不说明了,请查看源码,

以上就是liferay中portlet的action处理流程了。

有关在liferay中以外部war方式整合的portlet的处理流程,请关注我的后续文章。

 

分享到:
评论
3 楼 liushl2001 2007-05-22  
我有个问题想请教,
在liferay的开发中,我遇到了这个问题

在struts-config.xml中我定义了转发路径如下:

<action path="/noticelist/viewnotice" type="mtn.gfkd.site.action.Notice_viewcontextAction" >
<forward name="success" path="/noticelist/index" redirect="true" /></action>

但是,在liferay中运行总是在第一个action响应到
return mapping.findForward("success")的时候就没有响应了,2个action独立访问都没有错误,请问是否是还要进行其他配置,liferay才能转发路径呢,我看liferay整个的源代码都没有这种例子,是它不支持这种方式吗?

如蒙答复,至为感谢。
liushl2001@163.com
2 楼 devilbaby 2007-01-05  
mainServlet的service是servlet-mapping的过滤,PortalRequestProcessor是struts controller的processor会对url做一定的处理
1 楼 devilbaby 2007-01-05  
每次action请求还会执行mainServlet的service然后跑PortalRequestProcessor

相关推荐

    liferay_portlet对象详解

    Portlet 技术的理解和应用是开发 Liferay 应用程序的关键。本文将深入解析 Portlet 的关键概念,包括 Portlet 请求与 URL、Portlet 模式和窗口状态。 1. Portlet 请求与 URL 在 Liferay 的 Portal 页面中,多个 ...

    liferay portlet demo

    5. **CRUD操作**:在"CRUDDemo-portlet"中,开发者可以学习如何创建portlet以处理数据库中的增删改查操作,这涉及到JSP/FreeMarker的表单处理、Action类的业务逻辑实现、Service Builder的数据访问等。 6. **...

    用struts1.X实现liferay portlet插件(HelloWorld)

    例如,你需要在portlet的doView方法中处理渲染请求,而在processAction方法中处理动作请求。 5. **HelloWorld示例**:在StrutsHelloWorld-portlet项目中,很可能包含一个简单的Action类,如HelloWorldAction,它...

    liferay 整合struts例子

    4. **Portlet开发**:在Liferay中,Struts Action可以通过实现Liferay的PortletAction接口来适应portlet环境。这样,Struts的请求处理机制就能与Liferay的portlet生命周期协同工作。 5. **部署与测试**:将整合后的...

    Liferay form机制及例子

    在用户界面中,如果portlet包含一个表单,用户填写并提交表单时,Liferay的表单处理流程会按照以下步骤进行: 1. **提交表单**:当用户点击提交按钮,浏览器会向服务器发送一个POST请求,该请求的目标是表单中的`...

    liferay学习资源

    在Liferay中,Struts Portlet是一种常见的开发模式,它结合了Liferay的portlet功能与Struts框架的MVC设计模式。Struts Portlet允许开发者利用Struts的结构和生命周期来构建portlet,从而实现更复杂的业务逻辑和用户...

    liferay的开发流程

    在Liferay Struts Portlet中,你需要在此文件中配置ActionMapping和ActionForward,以指定用户请求如何被处理。 5. **Action和ActionForm**: 创建Action类来处理用户的请求,这些类通常继承自`...

    Liferay in Action完整版

    - **数据驱动的Portlet开发**:讲解了如何基于Liferay的数据模型快速开发Portlet应用,简化开发流程。 - **MVC架构下的Liferay开发**:深入探讨了Liferay框架下Model-View-Controller(MVC)模式的应用实践,帮助...

    liferay portal(jsp)开发指南

    《Liferay Portal JSP开发指南》 ...理解这些基本概念和流程,对于高效地开发和维护Liferay Portlet至关重要。在实际开发中,开发者还需要掌握Liferay API、服务构造、权限管理等高级特性,以实现更复杂的功能。

    liferay_4_portlet_development_guide

    - 为了更好地管理和组织Portlet,Liferay支持将它们归类到不同的类别中。这有助于提高开发效率和维护便利性。 - **Liferay Portlet框架** - 介绍了如何使用Liferay提供的框架编写简单的JSP Portlet和Struts ...

    Liferay in action

    Liferay is a different portal. 10分下载的, 打包5折提供下载. Part 1 Introduction to Liferay 1. Liferay is a different portal 2. Getting started with the Liferay development platform Part 2 Adding ...

    liferay_使用struts2开发portlet

    通过上述步骤,我们可以了解到在Liferay环境中使用Struts2开发Portlet的具体流程。整个过程涉及了开发环境的搭建、项目创建、Portlet类的编写以及Struts配置文件的设置等多个环节。这些步骤不仅为初学者提供了清晰的...

    liferay 使用struts2 开发portlet

    在本文中,我们将深入探讨如何使用Struts2框架在Liferay平台上开发Portlet。首先,我们需要准备相关的开发环境和依赖库。Liferay是一款开源的企业级门户平台,而Struts2是一个流行的MVC(模型-视图-控制器)框架,...

    struts2+liferay集成

    1. **Portlet**:Liferay中的基本单元,它是portlet容器内的Web应用程序,可以被部署到门户上,提供独立的功能和交互界面。 2. **Struts2 Action**:Struts2框架中的核心组件,负责接收用户的请求,执行相应的业务...

    struts-portlet

    4. **PortletAction**:处理portlet的业务逻辑,但需要考虑portlet生命周期(如初始化、渲染、事件处理等)。 5. **PortletTiles**:与Tiles集成,使portlet能利用预定义的视图模板。 6. **Portlet JSP**:遵循...

    File-Upload-Liferay-Portlet-with-JQuery

    在本文中,我们将深入探讨如何使用JQuery在Liferay Portlet中实现文件上传功能。Liferay Portlet是一种基于Java的框架,允许开发人员构建可重用的、自包含的Web组件,这些组件可以在Liferay Portal中运行。JQuery,...

    liferay portal 开发实例

    在Liferay Portal中,Portlet是展示内容的基本单元,它可以通过MVC模式来实现业务逻辑、数据处理和视图呈现的分离。MVC架构允许开发者将程序分为三个主要部分:模型(Model)负责数据处理和业务逻辑,视图(View)...

    liferay-portal详解

    本文档将从架构解析、portal 规范、portlet 容器、portlet 生命周期、liferay portal 工作原理等方面对 Liferay Portal 进行详细介绍。 第一部分:Liferay Portal 架构解析 Liferay Portal 的架构主要由三个部分...

    struts2_spring_json.rar_liferay struts2 json_portlet json_spring

    3. **Portlet生命周期**:理解portlet的init、render、action和destroy等生命周期方法,以及如何在这些方法中处理JSON请求。 4. **JSON数据模型**:掌握如何定义和序列化Java对象为JSON格式,可能涉及到Gson或...

    Liferay7.0自定义登录实例

    在Portlet的Java代码中,你需要实现`ActionRequest`和`ActionResponse`接口来处理登录请求。这通常在`Portlet类`的`processAction`方法中完成。当用户点击登录按钮时,表单数据将被发送到服务器,你在这里捕获这些...

Global site tag (gtag.js) - Google Analytics