【问题标题】:JSP EL private static class inside JSPJSP 内部的 JSP EL 私有静态类
【发布时间】:2012-07-17 23:37:20
【问题描述】:

我有以下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 class 更改为 public static class - 一切正常。

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

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

【问题讨论】:

  • 更新:但是,如果 private static class &lt;c:forEach var="item" items="${ITEMS}"&gt; ${item.class.name} &lt;/c:forEach&gt; 返回 org.apache.jsp.test_jsp$Test 所以 EL 不会将 ${item} 转换为字符串...它只是不能接受 ${item.val1}出于某种原因...没有更强烈地理解它...
  • 简单地说:类和getter需要对BeanELResolver可见。因此是公开的,而不是私人的。

标签: class jsp static el private


【解决方案1】:

JSPs 被 JSP 引擎翻译成servlets。 EL 表达式在运行时由EL engine 求值。

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

这是来自您的forEach 的一个 sn-p,由 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 要求使用无参数构造函数的公共类。

【讨论】:

    【解决方案2】:

    我没有所有的答案,但我可以帮助你一点。 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

    【讨论】:

      【解决方案3】:

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

      • 复合ELResolver
        • ImplicitObjectELREsolver
        • 复合ELResolver
          • 插件ELResolver
        • MapELResolver
        • ResourceBundleELResolver
        • ListELResolver
        • ArrayELResolver
        • BeanELResolver
        • ScopedAttributeELResolver

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

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

      【讨论】:

        猜你喜欢
        • 2016-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-17
        • 1970-01-01
        • 2019-09-19
        • 1970-01-01
        相关资源
        最近更新 更多