Java 未找到JSP、EL属性

Java 未找到JSP、EL属性,java,jsp,jstl,el,Java,Jsp,Jstl,El,为了学习这项技术,我正在用JSP创建一个简单的留言簿。目前我有两个类:guestbook/guestbook.class和guestbook/Entry.class(我还没有完成应用程序,所以我只有这些类),它们被添加到WEB-INF/libs/中,并且它们被正确地包含。在我的index.jsp文件中,我使用guestbook.guestbook类;它的方法返回向量。当我迭代条目并希望打印条目的作者时,我可以看到: javax.el.PropertyNotFoundException: Prop

为了学习这项技术,我正在用JSP创建一个简单的留言簿。目前我有两个类:guestbook/guestbook.class和guestbook/Entry.class(我还没有完成应用程序,所以我只有这些类),它们被添加到WEB-INF/libs/中,并且它们被正确地包含。在我的index.jsp文件中,我使用guestbook.guestbook类;它的方法返回向量。当我迭代条目并希望打印条目的作者时,我可以看到:

javax.el.PropertyNotFoundException: Property 'author' not found on type guestbook.Entry
我必须补充一点,Entry类是public,author属性是这样声明的:

public String author;
所以它也是公开的。这是我迭代条目时的代码:

<c:forEach items="${entries}" varStatus="i">
  <c:set var="entry" value="${entries[i.index]}" />
  <li><c:out value="${entry.author}" /></li>
</c:forEach>
返回留言簿

这些类位于PackageGuestBook中(您可以猜到),entries向量被传递到pageContext


我不知道我这样做有什么不对。谁能帮我一下吗?(提前感谢!)

JSP EL不会识别类中的公共字段,它只与getter方法一起工作(这是一个很好的实践,永远不要像这样将类的状态公开为公共字段)

所以使用

private String author;

public String getAuthor() {
   return author;
}
而不是

public String author;
另外,您的JSTL过于复杂,可以简化为:

<c:forEach items="${entries}" var="entry">
  <li><c:out value="${entry.author}" /></li>
</c:forEach>

  • 甚至

    <c:forEach items="${entries}" var="entry">
      <li>${entry.author}</li>
    </c:forEach>
    
    
    
  • ${entry.author}
  • 虽然后一种形式的XML不会转义作者姓名,但不建议这样做


    最后,
    Vector
    类已过时,应改用
    ArrayList

    如果找不到getter,还可以修改EL解析器以访问公共字段。为此,您首先需要创建特殊的ELResolver:

    public class PublicFieldSupportingELResolver extends ELResolver {
    
        @Override
        public Class<?> getCommonPropertyType(ELContext context, Object base) {
            return null;
        }
    
        @Override
        public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
            return null;
        }
    
        @Override
        public Class<?> getType(ELContext context, Object base, Object property) {
            return null;
        }
    
        @Override
        public Object getValue(ELContext context, Object base, Object property) {
            try {
                return context.getELResolver().getValue(
                        context, base, property);
            } catch(RuntimeException ex) {
                if(property instanceof String && base != null) {
                    try {
                        Field field = base.getClass().getDeclaredField((String) property);
                        Object value = field.get(base);
                        context.setPropertyResolved(true);
                        return value;
                    } catch (Exception e) {
                        throw new PropertyNotFoundException(e);
                    }
                } else {
                    throw ex;
                }
            }
        }
    
        @Override
        public boolean isReadOnly(ELContext context, Object base, Object property) {
            return false;
        }
    
        @Override
        public void setValue(ELContext context, Object base, Object property, Object value) {
        }
    }
    
    最后,您需要在servlet启动时运行这个configurer类。通过在web.xml中添加此类作为servlet侦听器来实现此目的:

      <listener>
        <listener-class>your.package.PublicFieldSupportingELResolverConfigurer</listener-class>
      </listener>
    
    
    your.package.publicfieldsupportingelresolverconfiguer
    

    现在,您可以在JSP中引用公共字段。

    我在构建路径中遇到了一个问题。
    javax.servlet.jsp.jstl-1.2.1.jar已删除,但未从生成路径中删除。将其从生成路径属性“xxx”中删除后,问题消失

    抛出StackOverflowException:)似乎
    返回context.getELResolver().getValue(context,base,property)
    调用相同的
    getValue
    实现。
    public class PublicFieldSupportingELResolverConfigurer implements ServletContextListener {
    
        public void contextInitialized(ServletContextEvent event) {
            JspFactory.getDefaultFactory()
                    .getJspApplicationContext(event.getServletContext())
                    .addELResolver(new PublicFieldSupportingELResolver());
        }
    
        public void contextDestroyed(ServletContextEvent event) {
        }
    }
    
      <listener>
        <listener-class>your.package.PublicFieldSupportingELResolverConfigurer</listener-class>
      </listener>