2011-11-27 5 views
8

이 기술을 배우기 위해 JSP로 간단한 방명록을 만듭니다. 현재 WEB-INF/libs /에 추가 된 방명록/GuestBook.class와 방명록/Entry.class (아직 앱을 끝내지 않았으므로이 클래스 만 포함)와 제대로 포함되어 있습니다. . 내 파일 index.jsp에서 guestbook.GuestBook 클래스를 사용하고 있습니다. 그 메소드는 Vector를 반환합니다. 내가 항목을 반복 내가 항목의 저자를 인쇄하고자 할 때, 나는 볼 수JSP, EL 속성을 찾을 수 없습니다.

javax.el.PropertyNotFoundException: Property 'author' not found on type guestbook.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은 클래스의 public 필드를 인식하지 못합니다. 이는 getter 메소드에서만 작동합니다 (어쨌든 우수 사례이므로 클래스의 상태를 이와 같이 공개 필드로 노출시키지 마십시오). 심지어

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

또는

:

그래서

private String author; 

public String getAuthor() { 
    return author; 
} 

대신 보조 노트로

public String author; 

사용하십시오 JSTL 지나치게 복잡, 그것은 단순화 할 수있다
<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) { 
    } 
} 

을에서 마지막으로 당신이 때이 설정자 수준을 실행해야 서블릿이 시작됩니다. 당신의 web.xml에 서블릿 리스너로이 클래스를 추가하여이 작업을 수행 :

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

지금 당신은 당신의 JSP를 공공 필드를 참조 할 수 있습니다.

+0

StackOverflowException가 발생합니다. return context.getELResolver(). getValue ( context, base, property);가 동일한 getValue 구현을 호출합니다. –

0

빌드 경로에 문제가 있습니다. javax.servlet.jsp.jstl-1.2.1.jar은 삭제되었지만 빌드 경로에서 제거되지 않았습니다. 'xxx'빌드 경로 속성에서 제거한 후 발견되지 않음 문제가 사라졌습니다.

관련 문제