2011-11-27 11 views
8

Je crée un livre d'or simple dans JSP afin d'apprendre cette technologie. Actuellement, j'ai deux classes: guestbook/GuestBook.class et guestbook/Entry.class (je n'ai pas encore terminé l'application, donc je n'ai que ces classes) qui sont ajoutés dans WEB-INF/libs/et ils sont inclus correctement . Dans mon fichier index.jsp j'utilise guestbook.GuestBook class; sa méthode renvoie Vector. Quand j'itérer sur les entrées et je voudrais imprimer un auteur de l'entrée, je peux voir:JSP, EL propriété non trouvée

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

Je dois ajouter que la classe d'entrée est publique et l'attribut auteur est déclaré de telle manière:

public String author; 

Donc c'est aussi public. Ceci est mon code quand j'itérer sur les entrées:

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

et

entry.class.name 

retours guestbook.Entry

Les cours sont dans le livre d'or de package (comme vous pouvez le deviner), les entrées vecteur est passé à pageContext.

Je ne sais pas quel est le problème avec ma façon de le faire. Quelqu'un peut-il m'aider s'il vous plaît avec ça? (Merci d'avance!)

Répondre

8

JSP EL ne reconnaît pas les champs publics dans vos classes, il ne fonctionne qu'avec les méthodes getter (ce qui est une bonne pratique de toute façon - n'exposez jamais l'état de vos classes à des champs publics comme celui-ci).

Il faut donc utiliser

private String author; 

public String getAuthor() { 
    return author; 
} 

au lieu de

public String author; 

Comme une note de côté, votre JSTL est trop compliqué, il peut être simplifié à:

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

ou même

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

Bien que cette dernière forme ne va pas XML-échapper le nom de l'auteur, n'est donc pas conseillé.

Enfin, la classe Vector est obsolète, vous devez utiliser ArrayList à la place.

3

Vous pouvez également modifier le résolveur EL pour accéder aux champs publics si un getter est introuvable. Pour ce faire, vous devez d'abord créer votre ELResolver spécial:

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) { 
    } 
} 

Ensuite, vous avez besoin d'une classe pour vous aider à configurer:

public class PublicFieldSupportingELResolverConfigurer implements ServletContextListener { 

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

    public void contextDestroyed(ServletContextEvent event) { 
    } 
} 

Enfin, vous devez exécuter ce configurateur-classe lorsque la La servlet démarre. Pour ce faire, en ajoutant cette classe comme un écouteur de servlet dans votre web.xml:

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

Maintenant, vous pouvez vous référer aux champs publics dans vos pages JSP.

+0

Lance une exception StackOverflowException :) Il semble que 'return context.getELResolver(). GetValue ( context, base, property);' appelle la même implémentation 'getValue'. –

0

J'ai rencontré un problème dans Build Path. javax.servlet.jsp.jstl-1.2.1.jar a été supprimé mais pas supprimé de Build Path. Après l'avoir supprimé de Build Path Property 'xxx', le problème non trouvé a disparu.