【问题标题】:Spring Web MVC huge performance issues when rendering viewSpring Web MVC 在渲染视图时出现巨大的性能问题
【发布时间】:2011-07-11 22:15:01
【问题描述】:

我正在使用 Spring Framework 制作一个项目,并使用 Spring MVC Framework 来构建我的视图。

现在一切正常,运行流畅,除了这个简单的 GET 页面需要 2 秒,有时需要更多时间才能在 localhost 上加载。

正如您在日志(链接)中看到的那样,GenericConversionService 非常慢,试图找到转换器来绑定属性。

非常感谢您的帮助!

提前致谢(为我的拼写错误道歉):)

更新:

显然,转换服务为“http://www.springframework.org/tags/form”命名空间中的每个(与 Path 属性绑定的)表单标签运行。我使用的表单标签越多,页面加载速度就越慢。我应该使用普通的 html 表单标签来提高性能还是有办法阻止它寻找“正确”的转换器?

其他信息:

日志: Link(滚动大约 1/3,您将看到大量 GenericConversionService 日志

Spring 洞察分析信息:

控制器(草率)代码:

@RequestMapping(value = "/route/create", method = RequestMethod.GET)
public ModelAndView getCreateRoute(){
    RouteCreateUpdateViewModel result = new RouteCreateUpdateViewModel();
    User u = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    u = us.get(u.getId());

    ModelAndView mav = new ModelAndView("route/create", "routeCreateUpdateModel", result);
    mav.addObject("favLocations", u.getLocations());
    mav.addObject("cars", u.getCars());

    result.setDateDay(Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + 1); // January = 0
    result.setDateMonth(Calendar.getInstance().get(Calendar.MONTH));
    result.setDateYear(Calendar.getInstance().get(Calendar.YEAR));

    mav.addObject("nextYear", result.getDateYear() + 1);

    return mav;
}

查看代码:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %>


<!-- //TODO I18N -->

<style type="text/css">
    li:focus {
        background-color:green;
    }
</style>

<script>
    var highlightedElement = null;
    $(document).ready(function(){
        $("input,select").click(function() {
            if(highlightedElement != null)
            {
                $(highlightedElement).removeClass("curFocus");
                if(highlightedElement.hasClass("location"))
                {
                    checkLocation(highlightedElement);
                }
            }
            var newHighlightedElement = $(this).parent().parent();
            $(newHighlightedElement).addClass("curFocus");
            highlightedElement = newHighlightedElement;
        });
    });

    function checkLocation(highlightedElement)
    {
        var parameters = {
        zipcode: $(highlightedElement).find(".zipcode").val(),
        street: $(highlightedElement).find(".street").val(),
        streetNr: $(highlightedElement).find(".streetNr").val()
        };

        $.getJSON('/location/validate.php', parameters, function(data) {
            if(data.result != null)
            {
                $(highlightedElement).removeClass("badData");
                $(highlightedElement).addClass("goodData");
            }
            else {
                $(highlightedElement).removeClass("goodData")
                $(highlightedElement).addClass("badData");
            }
        });
    }

</script>

<div>
    <h1><fmt:message key="route.create.header"/></h1>
    <div class="form-container">
        <c:url value="/route/create.php" var="actUrl"/>
        <form:form method="POST" action="${actUrl}" modelAttribute="routeCreateUpdateModel">
            <ul>
                <li class="location">
                    <form:label path="fromZipcode" cssClass="title">Van<span class="required">*</span></form:label>
                <span>
                    <form:input path="fromZipcode" cssClass="zipcode"/>
                    <form:label path="fromZipcode" cssClass="desc">Gemeente</form:label>
                </span>
                <span>
                    <form:input path="fromStreet" cssClass="street"/>
                    <form:label path="fromStreet" cssClass="desc">Straat</form:label>
                </span>
                <span>
                    <form:input path="fromStreetNr" cssClass="streetNr"/>
                    <form:label path="fromStreetNr" cssClass="desc">Nr</form:label>
                </span>
                </li>
                <li class="location">
                    <form:label path="toZipcode" cssClass="title">Naar<span class="required">*</span></form:label>
                <span>
                    <form:input path="toZipcode" cssClass="zipcode"/>
                    <form:label path="toZipcode" cssClass="desc">Gemeente</form:label>
                </span>
                <span>
                    <form:input path="toStreet" cssClass="street"/>
                    <form:label path="toStreet" cssClass="desc">Straat</form:label>
                </span>
                <span>
                    <form:input path="toStreetNr" cssClass="streetNr"/>
                    <form:label path="toStreetNr" cssClass="desc">Nr</form:label>
                </span>
                </li>
                <li>
                    <form:label path="dateDay" cssClass="title">Datum<span class="required">*</span></form:label>
                <span>
                   <tags:showDayPicker path="dateDay" currentDay="${routeCreateUpdateModel.dateDay}"/>
                    <form:label path="dateDay" cssClass="desc">dd</form:label>
                </span>
                <span>
                   <tags:showMonthPicker path="dateMonth" currentMonth="${routeCreateUpdateModel.dateMonth}"/>
                    <form:label path="dateMonth" cssClass="desc">mm</form:label>
                </span>
                <span>
                   <tags:showYearPicker path="dateYear" startYear="${routeCreateUpdateModel.dateYear}"
                                        stopYear="${nextYear}"/>
                    <form:label path="dateYear" cssClass="desc">yyyy</form:label>
                </span>
                </li>
                <li>
                     <form:label path="days" cssClass="title">Dagen<span class="required">*</span></form:label>
                    <span>
                        <form:checkbox path="days" value="1"/>
                        <form:label path="days" cssClass="desc">Ma</form:label>
                    </span>
                    <span>
                        <form:checkbox path="days" value="2"/>
                        <form:label path="days" cssClass="desc">Di</form:label>
                    </span>
                    <span>
                        <form:checkbox path="days" value="3"/>
                        <form:label path="days" cssClass="desc">Wo</form:label>
                    </span>
                    <span>
                        <form:checkbox path="days" value="4"/>
                        <form:label path="days" cssClass="desc">Do</form:label>
                    </span>
                    <span>
                        <form:checkbox path="days" value="5"/>
                        <form:label path="days" cssClass="desc">Vrij</form:label>
                    </span>
                    <span>
                        <form:checkbox path="days" value="6"/>
                        <form:label path="days" cssClass="desc">Za</form:label>
                    </span>
                    <span>
                        <form:checkbox path="days" value="7"/>
                        <form:label path="days" cssClass="desc">Zo</form:label>
                    </span>
                </li>
                <li>
                    <form:label path="stopDateDay" cssClass="title">Herhalen tot<span class="required">*</span></form:label>
                <span>
                   <tags:showDayPicker path="stopDateDay" currentDay="${routeCreateUpdateModel.dateDay}"/>
                    <form:label path="stopDateDay" cssClass="desc">dd</form:label>
                </span>
                <span>
                   <tags:showMonthPicker path="stopDateMonth" currentMonth="${routeCreateUpdateModel.dateMonth}"/>
                    <form:label path="stopDateMonth" cssClass="desc">mm</form:label>
                </span>
                <span>
                   <tags:showYearPicker path="stopDateYear" startYear="${routeCreateUpdateModel.dateYear}"
                                        stopYear="${nextYear}"/>
                    <form:label path="stopDateYear" cssClass="desc">yyyy</form:label>
                </span>
                </li>
                <li>
                    <form:label path="departureTime" cssClass="title">Vertrek uur<span class="required">*</span></form:label>
                    <span>
                        <tags:showHourPicker path="departureTime"/>
                        <form:label path="departureTime" cssClass="desc">uu</form:label>
                    </span>
                    <span>
                        <tags:showMinutePicker path="departureTime"/>
                        <form:label path="departureTime" cssClass="desc">mm</form:label>
                    </span>
                </li>
                <li>
                    <form:label path="arrivalTime" cssClass="title">Aankomst uur<span class="required">*</span></form:label>
                    <span>
                        <tags:showHourPicker path="arrivalTime"/>
                        <form:label path="arrivalTime" cssClass="desc">uu</form:label>
                    </span>
                    <span>
                        <tags:showMinutePicker path="arrivalTime"/>
                        <form:label path="arrivalTime" cssClass="desc">mm</form:label>
                    </span>
                </li>
                <li>
                    <form:label path="car" cssClass="title">Auto</form:label>
                    <span>
                        <form:select path="car">
                            <form:options items="${cars}" itemLabel="carName" itemValue="Id" />
                        </form:select>
                    </span>
                </li>
            </ul>
            <input type="submit" value="Route toevoegen"/>
        </form:form>
    </div>
</div>

如果您需要更多信息,请询问,我会立即提供。

再次感谢:)

【问题讨论】:

  • 更新感谢您的快速响应! :)
  • 你的自定义标签(tags:showMinutePicker等)是什么样子的?
  • 像这样:paste2.org/p/1292448

标签: spring spring-mvc spring-security


【解决方案1】:

我是 Spring MVC 开发人员中的一员……您介意分享一下您正在使用的 Spring Framework 版本吗?在最近的维护修订中引入了许多转换服务优化。

另外,您是否尝试过禁用 org.springframework.core.convert 的 DEBUG 日志记录,看看是否会有所改善?

谢谢, 基思

【讨论】:

  • 抱歉,Keith 回复晚了,我在 3.0.0.RELEASE 上运行
  • Yes 建议至少升级到最新的 3.0.x 版本以获得性能改进。
【解决方案2】:

可能是&lt;form:option&gt;标签中的类型转换次数过多引起的。

对于不需要类型转换的简单值,您可以按原样使用 HTML &lt;option&gt; 标签:

<form:select path="${path}">
    <c:forEach var="i" begin="0" end="59" step="${interval}">
      <option value="${i}"><fmt:formatNumber value="${i}" minIntegerDigits="2" /></option>
    </c:forEach>
</form:select>

作为更积极的优化,您可以去掉 &lt;c:forEach&gt;&lt;fmt:formatNumber&gt;,并使用预生成的 HTML 填充 &lt;form:select&gt; 的正文。

【讨论】:

  • 删除所有 form:option 标签并用普通标签标签替换所有 form:label 标签确实提高了性能。我想知道为什么表单标签如此缓慢,以及为什么它试图将字符串转换为字符串大声笑“寻找转换器以从 TypeDescriptor java.lang.String 转换为 TypeDescriptor java.lang.String”嗯?也许 Spring MVC 框架是一个糟糕的选择。非常感谢您的帮助:)
  • String->字符串转换仍可能导致后处理,例如修剪和基于字符串的格式化(例如,应用掩码)。如果不需要此类字符串处理,则转换服务应执行快速无操作操作。
猜你喜欢
  • 2011-05-26
  • 1970-01-01
  • 1970-01-01
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 2013-03-12
  • 1970-01-01
相关资源
最近更新 更多