Java 如何在Struts 2中访问OGNL跟踪评估?

Java 如何在Struts 2中访问OGNL跟踪评估?,java,jsp,struts2,struts,ognl,Java,Jsp,Struts2,Struts,Ognl,我被告知优化一个web应用程序。为此,我使用 我注意到大部分响应时间都花在了表示层上。特别是,当代码构建HTML代码时 深入研究这个瓶颈,我发现代码处理了很多OGNL类/方法(近50%的调用) 我通过删除一些不必要的OGNL语句对JSP代码进行了调优(详见下文)。我设法跑了200米。然而,代码在这个瓶颈上的平均花费仍然超过2000毫秒。总体响应时间约为3000毫秒 报告说: 从OGNL 2.5.0开始,OgnlContext对象可以自动跟踪表达式的计算。(…)您可以通过OgnlContext的l

我被告知优化一个web应用程序。为此,我使用

我注意到大部分响应时间都花在了表示层上。特别是,当代码构建HTML代码时

深入研究这个瓶颈,我发现代码处理了很多OGNL类/方法(近50%的调用)

我通过删除一些不必要的OGNL语句对JSP代码进行了调优(详见下文)。我设法跑了200米。然而,代码在这个瓶颈上的平均花费仍然超过2000毫秒。总体响应时间约为3000毫秒

报告说:

从OGNL 2.5.0开始,OgnlContext对象可以自动跟踪表达式的计算。(…)您可以通过OgnlContext的lastEvaluation属性访问上次评估

既然我使用的是Struts 2.3.15.1(OGNL v3.0.6),那么我如何从JSP文件或Action类访问该属性或调用
OgnlContext
getLastEvaluation


JSP文件

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix ="s" uri="/struts-tags" %>
<!DOCTYPE html>

<html>
<head>
<title><s:text name="domain.domain0.title"/></title>
<script type="text/javascript" src="<s:url value='/js/domain/domain0.js'/>"></script>
<script type="text/javascript" src="<s:url value='/js/core/html.js'/>"></script>
</head>
<body>
    <div style="width:100%;color:green;font-weight: bold;text-align:center">
        <s:text name="domain.domain0.information"/>
    </div>
    <div class="content selectFen">
        <s:set var="noAnchor">false</s:set>
        <s:iterator value="artefactList" status="numRow">
            <s:if test="court == nomenclatureCritere && #noAnchor!=true">
                <s:set var="noAnchor">true</s:set>
                <a id="NomencAnchor" href="#NomencAnchor" style="visibility:hidden;"></a>
            </s:if>
            <s:set var="isOpen" value="nomenclatureCritere.startsWith(court) || ligProd != '80'"/>
            <div class="parcoursNomenc">
                <table onmouseover='this.style.backgroundColor="gainsboro"' onmouseout='this.style.backgroundColor=""' style="width: 100%;font-weight:bolder">
                    <tbody>
                        <tr>
                            <s:url var="childNomenUrl" action="ajaxPopupNomenChild" escapeAmp="false">
                                <s:param name="dateCritere" value="dateCritere"/>
                                <s:param name="sidNomenclaturePere" value="sidArtNomenc"/>
                            </s:url>
                            <s:if test="#isOpen">
                               <s:if test="#numRow.last">
                                   <td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="open_last">&#160;</td>
                               </s:if>
                               <s:else>
                                   <td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="open">&#160;</td>
                               </s:else>
                            </s:if>
                            <s:else>
                               <s:if test="#numRow.last">
                                   <td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="closed_last">&#160;</td> 
                               </s:if>
                               <s:else>
                                   <td onclick="noeudPlusMoins(this);loadChild('<s:property value="childNomenUrl" />', 'divParcours<s:property value="sidArtNomenc"/>')" class="closed">&#160;</td>
                               </s:else>
                            </s:else>
                            <td style="vertical-align: top; width: 8.5em; padding-top: 5px;">
                                <s:text name="domain.domain0.label"/> <s:property value="court"/>
                            </td>
                            <td class="description">
                                <s:property value="description"/>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <div id="divParcours<s:property value="sidArtNomenc"/>" class="<s:if test="numRow.last">subtree_last</s:if><s:else>subtree</s:else>" >
                   <s:if test="#isOpen">
                       <s:action name="popupNomenExist" executeResult="true"> 
                          <s:param name="dateCritere" value="dateCritere"/> 
                          <s:param name="nomenclatureCritere" value="nomenclatureCritere"/>
                       </s:action>
                       <s:action name="ajaxPopupNomenChild" executeResult="true"> 
                          <s:param name="dateCritere" value="dateCritere"/>
                          <s:param name="sidNomenclaturePere" value="sidArtNomenc"/>
                       </s:action>
                    </s:if>
                </div>
           </div>
        </s:iterator>
    </div>
</body>
</html>

假的
真的
 
 
  
 
您可以像

有关如何跟踪评估的说明,请参见您在本节中链接的文档


您还可以在实例化上下文以启用此功能之前设置系统属性
ognl.traceEvaluations

查看JSP代码,很明显,罪魁祸首是
标记:

在每次迭代中调用两个操作。。。根据迭代的行数,这可能会成为一个严重的问题

我会尝试重构该部分;瓶颈的很大一部分在于解释标记、调用操作、通过拦截器堆栈等的机制

如果您可以生成相同的输出,从而最小化对操作的调用,那么瓶颈将显著减少。

注意:一个非常小的优化是更改S:if中布尔值和字符串比较的顺序,以利用短路(布尔值比较更快):

编辑


没有
s:action
它工作得更好,但是页面需要它们,我不知道如何替换它们

更清楚地说,应该采取行动

  • 执行一个(或几个)逻辑动作
  • 永远不要用作帮助器类
当您调用
popupNomenExist
时,您唯一的需求就是调用服务器,做一些事情,并接收结果以将其注入JSP

有几种方法可以得到这样的结果,而采取行动可能是最糟糕的(就表现而言,由于上面列出的原因)

您可以从
popupNomenExist
操作的
execute()
方法获取代码,并且:

  • 将它放在你当前行动的方法中,如罗马语链接答案中所述
  • 将其放置在helper类的静态方法中
  • 在当前操作中预先计算它,并将结果显示为字符串列表
  • 等等

  • 此外,我们无法争论popupNomenExist的
    execute()
    方法中到底执行了什么,但我想它可能会被重构,以防止执行每个迭代所共有的部分逻辑,将它们分组,并在迭代之前作为一种缓存执行。

    2000ms?您能展示一个示例JSP吗?还考虑升级到至少2.3.153由于安全性reasons@AndreaLigios我已将JSP文件内容添加到我的问题中。ServletContextListener是否适合初始化系统属性?是的,您可以在应用程序启动时执行此操作,请注意,您也可以在
    DispatcherListener
    中执行此操作。关于JSP还有一件事:如果您想要更好的性能,请去掉
    s:action
    标记。我可以用什么来代替
    s:action
    标记?如果我必须自己生成完整的url,他们的执行工作似乎相当困难。请使用操作属性。@Stephan他们是对的,应该不惜一切代价避免使用s:action标记。每次使用该标记时,就好像您从url(包括拦截器)调用了该操作一样,在迭代器中逐行执行此操作非常昂贵#noAnchor比
    快#noAnchor=true
    ?否。我的意思是,由于两个表达式(布尔=布尔和对象=对象)位于and中,并且由于短路,如果第一个表达式为false,则不会计算第二个表达式,将最快的表达式作为第一个wil
    OgnlContext context = (OgnlContext) ActionContext.getContext().getValueStack().getContext();
    context.setTraceEvaluations(true); 
    Evaluation evaluation = context.getLastEvaluation();