马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。如果您注册时有任何问题请联系客服QQ: 83569622 。
您需要 登录 才可以下载或查看,没有帐号?注册
x
1,了解portlet render请求处理流程 前边已经有文章对此作了介绍但我们认然将我们要说的内容放在这里 portlet render请求和portlet action请求的差别是什么呢 1 portlet action 请求会调用portlet.processAction 处理你的任务, 然后再调用res.sendRedirect(String path)。(不论你是否显式调用) 如果你没有直接调用那么他就会调用默认的 portlet render url 。这是它有发出了render请求 2 在调用porlet render 后,liferay 门户同样请求到 com.liferay.portal.action.LayoutAction String action = ParamUtil.getString(req, "p_p_action"); 这里的action =0 就是 porlet render请求 if (action.equals("0")) { _processRenderRequest(req, res); //这里作了些啥工作呢? } 这里其实只是对当前portlet 的state 和mode作了简单的调整 并没有做其他工作 return mapping.findForward("portal.layout"); 然后他就直接刷新了整个portal ,也就是对整个门户系统的所有portlet都作了render 调用(很恐怖呀!!!) 你现在知道它为何比较慢了 3 这时我们再细微的对liferay的页面整合做初步的了解 portal.layout 其实直接请求了/html/portal/layout.jsp <c:choose> <c:when test='<%= Validator.isNull(ParamUtil.getString(request, "p_p_id")) %>'> <liferay-util:include page="<%= Constants.TEXT_HTML_DIR + PortalUtil.getLayoutViewPage(layout) %>" /> </c:when> <c therwise> <liferay-util:include page='<%= Constants.TEXT_HTML_DIR + "/portal/layout/view/portlet.jsp" %>' /> </c:otherwise> </c:choose> 我们通过了解发现p_p_id 是记录请求portlet id的 。当我们操作的是portal的时候 p_p_id is null 其他情况我们都会调用 /portal/layout/view/portlet.jsp页面
boolean layoutMaximized = layoutTypePortlet.hasStateMax(); if (!layoutMaximized) { String content = LayoutTemplateLocalUtil.getContent(layoutTypePortlet.getLayoutTemplateId(), false, theme.getThemeId()); RuntimePortletUtil.processTemplate(application, pageContext, request, response, content); } else { String content = null; if (themeDisplay.isStateExclusive()) { content = LayoutTemplateLocalUtil.getContent("exclusive", true, theme.getThemeId()); } else { content = LayoutTemplateLocalUtil.getContent("max", true, theme.getThemeId()); } RuntimePortletUtil.processTemplate(application, pageContext, request, response, StringUtil.split(layoutTypePortlet.getStateMax())[0], content); } 从这里我们可以看到 LayoutTemplateLocalUtil.getContent ,RuntimePortletUtil.processTemplate
{ // 读取模板内容,模板由liferay-layout-templates.xml文件定义. String content = LayoutTemplateLocalUtil.getContent( layoutTypePortlet.getLayoutTemplateId(), false, theme.getThemeId());
// 处理模板 portlet.layoutconfiguration.util.RuntimePortletUtil.processTemplate( application, pageContext, request, response, content); // 注入模板处理程序 TemplateProcessor processor = new TemplateProcessor(ctx, req, res, portletId); VelocityContext context = new VelocityContext(); context.put("processor", processor); // 处理模板 Velocity.evaluate(context, pageContext.getOut(), RuntimePortletUtil.class.getName(), content); 这里的信息来自 http://billy.javaeye.com/blog/35822 } portlet.layoutconfiguration.util.RuntimePortletUtil 这里是 public static void processTemplate( ServletContext ctx, PageContext pageContext, HttpServletRequest req, HttpServletResponse res, String portletId, String content) throws Exception { if (Validator.isNull(content)) { return; } //处理模板 TemplateProcessor processor = new TemplateProcessor(ctx, req, res, portletId); VelocityContext vc = new VelocityContext(); //注入模板 vc.put("processor", processor); VelocityVariables.insertVariables(vc, ctx, req, pageContext); StringWriter sw = new StringWriter(); try { //处理模板 Velocity.evaluate( vc, sw, RuntimePortletUtil.class.getName(), content); } catch (Exception e) { _log.error(StackTraceUtil.getStackTrace(e)); throw e; }
String output = sw.toString(); //获取 column信息 Map columnsMap = processor.getColumnsMap(); Iterator itr = columnsMap.entrySet().iterator(); while (itr.hasNext()) { Map.Entry entry = (Map.Entry)itr.next(); String key = (String)entry.getKey(); String value = (String)entry.getValue();
output = StringUtil.replace(output, key, value); } //这是新的带有portlet 具体位置的模板 output
//取得当前页的portlet Map portletsMap = processor.getPortletsMap(); itr = portletsMap.entrySet().iterator(); while (itr.hasNext()) { Map.Entry entry = (Map.Entry)itr.next(); Portlet portlet = (Portlet)entry.getKey(); Object[] value = (Object[])entry.getValue(); String rootPortletId = (String)value[0]; String instanceId = (String)value[1]; String queryString = (String)value[2]; String columnId = (String)value[3]; Integer columnPos = (Integer)value[4]; Integer columnCount = (Integer)value[5]; StringBuffer sb = new StringBuffer(); //处理单独的一个portlet信息 RuntimePortletUtil.processPortlet( sb, ctx, req, res, null, null, rootPortletId, instanceId, queryString, columnId, columnPos, columnCount);
output = StringUtil.replace( output, "[$TEMPLATE_PORTLET_" + portlet.getPortletId() + "$]", sb.toString()); } //产生最后的页面 pageContext.getOut().print(output); }
在 处理RuntimePortletUtil.processPortlet时 public static void processPortlet( StringBuffer sb, ServletContext ctx, HttpServletRequest req, HttpServletResponse res, RenderRequest renderRequest, RenderResponse renderResponse, String portletId, String instanceId, String queryString, String columnId, Integer columnPos, Integer columnCount, String path) throws Exception { //。。。portlet的一些初始化信息 try { //对portlet发出render请求 PortalUtil.renderPortlet( sb, ctx, req, res, portlet, queryString, columnId, columnPos, columnCount, path); } finally { portletDisplay.copyFrom(portletDisplayClone); try { PortletDisplayFactory.recycle(portletDisplayClone); } catch (Exception e) { _log.error(e); } _defineObjects( req, portletConfig, renderRequest, renderResponse); } } Render portlet 请求的页面 PortalUtil.renderPortlet( public static void renderPortlet( StringBuffer sb, ServletContext ctx, HttpServletRequest req, HttpServletResponse res, Portlet portlet, String queryString, String columnId, Integer columnPos, Integer columnCount, String path) throws IOException, ServletException { //...初始话porlet的一些参数 //其实path就一直为null if (path == null) { path = "/html/portal/render_portlet.jsp"; //其实render_portlet.jsp是请求portlet的具体实施者 } //根据上边的参数 我们可以获得portlet的页面片段 RequestDispatcher rd = ctx.getRequestDispatcher(path); if (sb != null) { StringServletResponse stringServletRes = new StringServletResponse(res); rd.include(req, stringServletRes); //将页面片段返回去用于拼整个页面 sb.append(stringServletRes.getString()); } else { // LEP-766 情况 } } 我们终于找到 render_portlet.jsp 在这里我们看的了我们需要的信息
//对porlet实施render 请求 cachePortlet.render(renderRequestImpl, renderResponseImpl); 4,那么如何实现ajax请求呢 改造整个liferay门户系统的工程实现ajax看上去有点大,但在portlet的局部实现ajax,是我现在的目标。 就是说我在我的portlet里的view或edit里的连接或按钮,可以使用脚本请求服务器然后返回我一个页面片段让我刷新我的portlet的内容。这个要求,我想本不过分。但是如果不改造liferay的话,我们是没法实现的。因为我们在页面处理上需要门户系统的一些信息 比如 <portlet:namespace /> 那么我现就开始改造了 com.liferay.portal.action.LayoutAction
public class LayoutAction extends Action { public ActionForward 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"); //在请求是增加参数 使用Ajax技术 String ajaxs=ParamUtil.getString(req, "p_p_ajax"); boolean ajax=ajaxs==null?false ajaxs.equals("true")?true:false); if (Validator.isNotNull(plid)) { try { if (action.equals("1")) { //action 部分 。。。 } else if (action.equals("0")) { _processRenderRequest(req, res); //Ajax页面直接返回 _log.debug("ajax -----------flag"+ajax); if (ajax) { //res.getWriter(). return null; } }
return mapping.findForward("portal.layout"); } catch (Exception e) { req.setAttribute(PageContext.EXCEPTION, e); return mapping.findForward(Constants.COMMON_ERROR); } finally { try { if (action.equals("1")) { ActionRequestImpl actionRequestImpl = (ActionRequestImpl)req.getAttribute( WebKeys.JAVAX_PORTLET_REQUEST); ActionRequestFactory.recycle(actionRequestImpl); } } catch (Exception e) { _log.error(e); } try { if (action.equals("1")) { ActionResponseImpl actionResponseImpl = (ActionResponseImpl)req.getAttribute( WebKeys.JAVAX_PORTLET_RESPONSE); ActionResponseFactory.recycle(actionResponseImpl); } } catch (Exception e) { _log.error(e); } //如果是ajax也需要关闭 try{ if (ajax) { RenderRequestImpl renderRequestImpl = (RenderRequestImpl)req.getAttribute( WebKeys.JAVAX_PORTLET_REQUEST); RenderRequestFactory.recycle(renderRequestImpl);
} }catch(Exception e){ _log.error(e); } try{ RenderResponseImpl renderResponseImpl = (RenderResponseImpl)req.getAttribute( WebKeys.JAVAX_PORTLET_RESPONSE); RenderResponseFactory.recycle(renderResponseImpl); } catch(Exception e) {_log.error(e);
}
} } else { try { _forwardLayout(req); return mapping.findForward(Constants.COMMON_FORWARD); } catch (Exception e) { req.setAttribute(PageContext.EXCEPTION, e); return mapping.findForward(Constants.COMMON_ERROR); } } } private Portlet _processPortletRequest( HttpServletRequest req, HttpServletResponse res, boolean action) throws Exception { //同样需要判断 String ajax=ParamUtil.getString(req, "p_p_ajax");
。。。 if (action) { 。。。//action 部分 } else { PortalUtil.updateWindowState( portletId, user, layout, windowState, req); PortalUtil.updatePortletMode(portletId, user, layout, portletMode); //从这里开始 _log.debug("ajax------------2"); //ajax的情况就是这样 if (ajax!=null&&ajax.equals("true")) { _log.debug("ajax------------2"+ajax); //调用catchePortlet.render String queryString = (String)req.getAttribute(WebKeys.RENDER_PORTLET_QUERY_STRING); //创建 renderRequestImpl RenderRequestImpl renderRequestImpl = RenderRequestFactory.create(req, portlet, cachePortlet, portletCtx, windowState, portletMode, prefs, layout.getPlid()); if (Validator.isNotNull(queryString)) { DynamicServletRequest dynamicReq = (DynamicServletRequest)renderRequestImpl.getHttpServletRequest(); String[] params = StringUtil.split(queryString, StringPool.AMPERSAND); for (int i = 0; i < params.length; i++) { String[] kvp = StringUtil.split(params, StringPool.EQUAL); dynamicReq.setParameter(kvp[0], kvp[1]); } } StringServletResponse stringServletRes = new StringServletResponse(res); //创建renderResponseImpl RenderResponseImpl renderResponseImpl = RenderResponseFactory.create(renderRequestImpl, stringServletRes, portletId,companyId,layout.getPlid()); renderRequestImpl.defineObjects(portletConfig, renderResponseImpl); //发出请求 cachePortlet.render(renderRequestImpl, renderResponseImpl); SessionMessages.clear(renderRequestImpl); SessionErrors.clear(renderRequestImpl); // _log.error("sxinfo----------ajax"+stringServletRes.getString()); //返回请求的页面片段 res.getWriter().print(stringServletRes.getString()); //到这里结束 } } return portlet; } } |