2011-11-27 118 views
8

我正在JSP中创建一个简单的留言簿以学习此技术。目前我有两个类:留言簿/ GuestBook.class和留言簿/ Entry.class(我还没有完成应用程序,所以我只有这些类),它们被添加到WEB-INF/libs /中,并且它们被正确包含。在我的文件index.jsp中,我使用了guestbook.GuestBook类;其方法返回Vector。当我遍历条目,我想打印的条目的作者,我可以看到:未找到JSP,EL属性

javax.el.PropertyNotFoundException: Property 'author' not found on type guestbook.Entry 

我必须补充的是Entry类是公共和作者属性以这样的方式宣布:

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> 

entry.class.name 

回报guestbook.Entry

类在包留言(你可以猜),参赛矢量传递给pageContext。

我不知道我的做法有什么问题。有人能帮助我吗? (在此先感谢!)

回答

8

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> 

虽然后一种形式不会XML转义作者姓名,所以不建议。

最后,Vector类已过时,您应该使用ArrayList来代替。

3

如果未找到吸气剂,您还可以修改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) { 
    } 
} 

然后,你需要一个类来帮助您进行配置:

public class PublicFieldSupportingELResolverConfigurer implements ServletContextListener { 

    public void contextInitialized(ServletContextEvent event) { 
     JspFactory.getDefaultFactory() 
       .getJspApplicationContext(event.getServletContext()) 
       .addELResolver(new PublicFieldSupportingELResolver()); 
    } 

    public void contextDestroyed(ServletContextEvent event) { 
    } 
} 

最后,你需要在运行此配置者级servlet启动。通过在web.xml中将此类添加为servlet侦听器来执行此操作:

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

现在您可以参考JSP中的公共字段。

+0

引发StackOverflowException :)看起来,'返回context.getELResolver()。getValue( 上下文,基地,财产);'调用相同的'getValue'实现。 –

0

我在构建路径中遇到问题。 javax.servlet.jsp.jstl-1.2.1.jar已被删除,但未从Build Path中删除。从构建路径属性'xxx'中删除后未发现问题消失。