【问题标题】:How do I iterate over all my model attributes on my JSP page?如何迭代我的 JSP 页面上的所有模型属性?
【发布时间】:2017-01-13 19:54:37
【问题描述】:

我将 Spring 3.2.11.RELEASE 与 JBoss 7.1.3.Final 和 Java 6 一起使用。我在控制器中有这个方法

@RequestMapping(value = "/method", method = RequestMethod.GET)
public String myMethod(final Model model,
                        final HttpServletRequest request,
                        final HttpServletResponse response,
                        final Principal principal) 

...
    model.addAttribute("paramName", "paramValue");

注意我如何将属性添加到我的模型中。我的问题是,在此页面所服务的 JSP 页面上,我如何遍历模型中的所有属性并将它们输出为隐藏输入字段,其中 INPUT 的名称是属性名称,值是我在使用该属性的模型?

编辑:响应给出的答案,这里是 JSP 解决方案的输出。请注意,其中没有模型属性。

        <input type='hidden' name='javax.servlet.jsp.jspRequest' value='org.springframework.web.context.support.ContextExposingHttpServletRequest@7a0a4c3f'>

        <input type='hidden' name='javax.servlet.jsp.jspPageContext' value='org.apache.jasper.runtime.PageContextImpl@3939794a'>

        <input type='hidden' name='appVersion' value='???application.version???'>

        <input type='hidden' name='javax.servlet.jsp.jspResponse' value='org.owasp.csrfguard.http.InterceptRedirectResponse@722033be'>

        <input type='hidden' name='javax.servlet.jsp.jspApplication' value='io.undertow.servlet.spec.ServletContextImpl@14c1252c'>

        <input type='hidden' name='org.apache.taglibs.standard.jsp.ImplicitObjects' value='javax.servlet.jsp.el.ImplicitObjectELResolver$ImplicitObjects@23c27a49'>

        <input type='hidden' name='javax.servlet.jsp.jspOut' value='org.apache.jasper.runtime.JspWriterImpl@b01a1ba'>

        <input type='hidden' name='javax.servlet.jsp.jspPage' value='org.apache.jsp.WEB_002dINF.views.lti.launch_jsp@1dcc48bf'>

        <input type='hidden' name='javax.servlet.jsp.jspConfig' value='io.undertow.servlet.spec.ServletConfigImpl@3fd40806'>

【问题讨论】:

    标签: spring jsp input jboss model


    【解决方案1】:

    模型属性是“请求范围”对象 您可以执行以下操作(我使用 JSTL):

        <c:forEach items="${requestScope}" var="par">
            <c:if test="${par.key.indexOf('attrName_') > -1}">
                <li>${par.key} - ${par.value}</li>
            </c:if>
        </c:forEach>
    

    由于没有过滤器,您将拥有所有请求范围对象,因此我按我们要检查的模型属性进行过滤

    我用这段代码测试过:

    @RequestMapping(method = { RequestMethod.GET }, value = { "/*" })
        public String renderPage(Model model) throws Exception
        {
            String requestedUrl = req.getRequestURI();
            int indice = requestedUrl.lastIndexOf('/');
            String pagina = requestedUrl.substring(indice + 1);
            try
            {
                String usernameUtente = "default username utente";
                if (StringUtils.hasText(getPrincipal()))
                {
                    usernameUtente = getPrincipal();
                }
                model.addAttribute("usernameUtente", usernameUtente);
                model.addAttribute("webDebug", webDebug);
                for(int i = 0; i<10; i++)
                {
                    model.addAttribute("attrName_"+i, "attrValue_"+i);
                }
                return pagina;
            }
            catch (Exception e)
            {
                String message = "Errore nell'erogazione della pagina " + pagina;
                logger.error(message, e);
                return "genericError";
            }
        }
    

    这就是我看到的输出(我省略了不相关的打印,但请注意您将打印所有请求范围对象:

    attrName_0 - attrValue_0
    attrName_1 - attrValue_1
    attrName_2 - attrValue_2
    attrName_3 - attrValue_3
    attrName_4 - attrValue_4
    attrName_5 - attrValue_5
    attrName_6 - attrValue_6
    attrName_7 - attrValue_7
    attrName_8 - attrValue_8
    attrName_9 - attrValue_9
    

    希望对你有帮助

    安杰洛

    【讨论】:

    • 这看起来真不错。一个问题,在您的解决方案中,是否所有属性都必须以特殊前缀开头才能使其起作用?如果我不按前缀过滤,还有哪些其他垃圾会打印到页面上?
    • 所有属性都有自己的键;遗憾的是,我不知道所有属性,因为其中一些属性可以由 Application Server 添加,其他属性可以由应用程序框架(例如 spring)添加,而其他属性可以由您添加……所以最好的办法可能是为所有属性添加前缀并只过滤这些
    • 不知道哪些是JBoss和Spring添加的?
    • 嗯...老实说我不知道​​...我看到 spring 总是使用完整的限定名称添加它们,但我不确定是否总是这样;关于JBoss...我完全不知道
    【解决方案2】:

    本质上,您只需要迭代所有页面属性。取决于您在 jsp 上使用的内容(scriptlet、jstl 或 html 的 thymeleaf 之类的东西):

    小脚本:

    <form>
        <% Session session = request.getSession();
        Enumeration attributeNames = session.getAttributeNames();
        while (attributeNames.hasMoreElements()) {
            String name = attributeNames.nextElement();
            String value = session.getAttribute(name);
        %>
            <input type='hidden' name="<% name %>" value="<% value %>">
        <%
            }
        %>
    </form>
    

    JSTL:

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    
    <h3>Page attributes:</h3>
    <form>
        <c:forEach items="${pageScope}" var="p">
            <input type='hidden' name='${p.key}' value='${p.value}'>
        </c:forEach>
     </form>
    

    百里香:

    <form>
        <input th:each="var : ${#vars}" type='hidden' name="${var.key}" value="${var.value}">
    </form>
    

    【讨论】:

    • 我尝试了您的 JSTL 解决方案(输出包含在我的问题中)。在我采取任何轻率行动之前,我想确保您理解我的问题。我正在寻找模型属性。输出的不是模型属性。这有意义吗?
    【解决方案3】:

    为了避免对 Spring 和 Servlet 容器添加的参数感到头疼,最好使用单独的映射将值传递到模型中。只需使用@ModelAttribute,Spring 就会自动创建并将其添加到模型中:

    @RequestMapping(value = "/method", method = RequestMethod.GET)
    public String myMethod(final Model model, @ModelAttribute("map") HashMap<String, Object> map) {
    
        map.put("paramName1", "value1");
        map.put("paramName2", "value2");
        //...and so on
    }
    

    现在您可以在 JSP 中迭代此地图:

    <c:forEach items="${map.keySet()}" var="key">
        <input type="hidden" name="${key}" value="${map[key]}"/>
    </c:forEach>
    

    您还可以通过以下方式访问地图的每个项目:

    <c:out value="${map.paramName1}"/>
    <c:out value="${map.paramName2}"/>
    ...
    

    如果您不需要某些参数是可迭代的,请将其添加到原始 ModelMap 而不是单独的映射中。

    【讨论】:

      【解决方案4】:

      您只需使用 Jstl 的 foreach 标签进行迭代。

       <c:forEach items="${requestScope}" var="var">
          <c:if test="${ !var.key.startsWith('javax.') && !var.key.startsWith('org.springframework')}">
              <input type="hidden" name="${var.key}" value="${var.value}" />
          </c:if>
       </c:forEach>
      

      来自 spring 框架和 Servlet 的请求属性确实有前缀,您不需要在请求属性中添加前缀。

      您可以忽略所有前缀为“org.springframework”或“javax”的属性。

      【讨论】:

        【解决方案5】:

        你可以试试这个:

        @RequestMapping(value = "/method", method = RequestMethod.GET)
        public String myMethod(final Model model,
                                final HttpServletRequest request,
                                final HttpServletResponse response,
                                final Principal principal) 
        
        ...
            //Create list for param names and another list for param values
            List<String> paramNames = new ArrayList();
            List<String> paramValues = new ArrayList();
            paramNames.add("paramName1");
            paramValues.add("paramValue1");
            paramNames.add("paramName2");
            paramValues.add("paramValue2");
            //paramValue1 is the value corresponding to paramName1 and so on...
            //add as many param names and values as you need 
            ...
            //Then add both lists to the model
            model.addAttribute("paramNames", paramNames);
            model.addAttribute("paramValues", paramValues);
        

        然后在JSP中,可以遍历paramNames列表,通过varStatus.index获取本轮迭代的索引,并用它从paramValues列表中拉取对应的param值的值。像这样-

         <form id='f' name='myform' method='POST' action='/path/to/servlet'>
           <c:forEach items="${paramNames}" var="paramName" varStatus="status">     
             <input type='hidden' name='${paramName}' value='${paramValues[status.index]}'>
           </c:forEach>
         </form>
        

        您可以根据需要将其他输入元素添加到表单中,但上述内容应为您在模型中设置的每个参数生成所有隐藏的输入元素。

        【讨论】:

        • 这需要一个额外的数据结构,所以每次我添加一个新的模型属性时,我还必须将它的参数名称添加到新的数据结构中,对吗?
        • 如上面的答案所示,您需要在两个单独的列表中添加参数名称和参数值。您只需要将这些参数名称和值添加到要为其生成隐藏输入元素的列表中。由于您将这些列表添加到模型属性中,如上所示,因此您不需要将参数名称直接添加到模型属性中。试试上面的例子是否对你有用
        • 这个想法是我只需在一个地方添加一次这些名称-值对。我希望隐藏的输入完全是存储在我的模型中的所有内容。如果我要维护一个单独的列表,我还不如每次在我的模型中添加一些东西时在页面上添加一个新的输入。
        • 为什么有两个列表?为什么不按照另一个答案中的建议使用 Map
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-17
        • 2011-04-06
        • 1970-01-01
        • 1970-01-01
        • 2015-10-24
        • 2022-01-25
        • 2013-06-08
        相关资源
        最近更新 更多