2011-11-27 160 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'中刪除後未發現問題消失。