3

我有以下jsp:

<%@ page import="java.util.Arrays" %>
<%@ page import="java.util.List" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html><body>
<%! 
private static class Test {
    private String val2;
    private String val1;

    public Test(String v1, String v2) {
        val1 = v1;
        val2 = v2;
    }

    public String getVal1() {
        return val1;
    }

    public String getVal2() {
        return val2;
    }
};

private static List<Test> ITEMS = Arrays.asList(new Test("1","1"),new Test("2","2"));

%>

<%
    pageContext.setAttribute("ITEMS",ITEMS);
%>

<c:forEach var="item" items="${ITEMS}">
    ${item.val1},${item.val2}
</c:forEach>
</body></html>

当 TOMCAT 执行它时 - 我们看到异常

javax.el.PropertyNotFoundException: Property 'val1' not readable on type java.lang.String

所以 EL 遍历集合,但由于某种原因,forEach 内部的 ${item} 变成了一个字符串。

但是,当您简单地更改private static classpublic static class- 时,一切正常。

我不明白这不是问题,因为我们有解决方案。但我只是不明白为什么在这种情况下它需要公开。JSP 被翻译成 servlet,所以在翻译后的 java 代码中它无论如何都能看到。EL 不只是获取对象属性的反射材料吗(在我们的例子中,属性是public,所以 EL 应该可以在没有反射修饰符的情况下获取它)。

如果有人知道 - 请回复。我将不胜感激!提前致谢。

4

3 回答 3

2

JSP由 JSP 引擎翻译成servlet。EL 表达式在运行时由EL 引擎求值。

当向 JSPTest声明private时,它的方法(默认情况下)通过对表达式语言引擎的自省是不可见的。

forEach以下是WebSphere Application Server 翻译的您的片段:

   do {
      out.write(_jsp_string4);
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl
         .proprietaryEvaluate("${item.val1}", java.lang.String.class,
                              (PageContext)pageContext, _jspx_fnmap, false));
      out.write(_jsp_string5);
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl
         .proprietaryEvaluate("${item.val2}", java.lang.String.class,
                              (PageContext)pageContext, _jspx_fnmap, false));
      out.write(_jsp_string1);
      int evalDoAfterBody = _jspx_th_c_forEach_0.doAfterBody();
      if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)
         break;
    } while (true);

EL 是为与 JavaBeans 一起使用而设计的;bean 要求使用无参数构造函数的公共类。

于 2012-07-19T09:38:06.343 回答
1

JSP 使用 ELResolver 的链解析 EL 变量。以下是 EL Resolver 链层次结构:

  • CompositeELResolver
    • 隐式对象ELREsolver
    • CompositeELResolver
      • 插件ELResolver
    • MapELResolver
    • ResourceBundleELResolver
    • ListELResolver
    • ArrayEL解析器
    • BeanEL解析器
    • ScopedAttributeELResolver

在此层次结构中,您item将使用 BeanELResolver 进行解析。BeanELResolver 要求对象遵循某些规则才能将其称为Bean. 一个这样的属性是,每个属性都应该有 setter 和 getter。

您看到的异常是因为您没有为 bean 中的属性定义 setter

于 2012-07-19T06:01:57.407 回答
1

我没有所有的答案,但我可以帮助你一点。Tomcat 使用 BeanELResolver 来定义使用 JavaBeans 组件架构的对象的属性解析行为。由于您没有遵守 JavaBean 约定,因此未定义行为。如果您使用,您可以获得更明智的错误消息

 private static class Test implements java.io.Serializable { 

这将导致

javax.el.PropertyNotFoundException: Property 'var1' not found on type org.apache.jsp.test_jsp$Test  

看看
http://docs.oracle.com/cd/E17802_01/products/products/jsp/2.1/docs/jsp-2_1-pfd2/javax/el/BeanELResolver.html
http://en.wikipedia.org/wiki /JavaBeans

于 2012-07-19T02:11:08.457 回答