javax.servlet.ServletException: javax.servlet.jsp.JspTagException: не знаю, как перебирать предоставленные «элементы» в <forEach> - PullRequest
7 голосов
/ 04 февраля 2012

У меня есть Бин, который содержит результаты. Мне нужно использовать JSTL, чтобы перебрать его и представить результаты. Вот этот боб:

public class DetResults
{
    private List<String> headings;
    private List<Class<?>> types;
    private List<Object[]> data;

    public DetResults() {}

    public List<String> getHeadings() { return this.headings; }
    public String getHeading(int which) { return this.headings.get(which); }

    public List<Class<?>> getTypes() { return this.types; }
    public Class<?> getType(int which) { return this.types.get(which); }

    public List<Object[]> getData( ) { return this.data; }
    public Object[] getDataAtRow( int row ) { return this.data.get(row); }


    public void setHeadings( List<String> val ) { this.headings = val; }
    public void setHeadings( String[] val ) { this.headings = Arrays.asList(val); }
    public void addHeading( String val ) 
    { 
        if( this.headings == null ) this.headings = new ArrayList<String>();
        this.headings.add(val); 
    }

    public void setTypes( List<Class<?>> val ) { this.types = val; }
    public void setTypes( Class<?> val[] ) { this.types = Arrays.asList(val); }
    public void addType( Class<?> val ) 
    {
        if( this.types == null ) this.types = new ArrayList<Class<?>>();
        this.types.add(val); 
    }


    public void setData( List<Object[]> val ) { this.data = val; }

    // allow NPE to get thrown
    public void setDataAtRow( Object[] val, int row ) { this.data.set(row, val); }

    public void appendDataRow( Object[] val ) 
    {
        if( data == null ) data = new ArrayList<Object[]>(); 
        this.data.add(val); 
    }

    public int getColumnCount() { return this.headings!=null?this.headings.size():0; }

}

Вот обработчик, который установит bean-компонент к JSP:

DetResults results = detDAO.fetchDetResults(paramBean);
request.setAttribute("results", results);
action.setJspURI(".../.jsp");

Я попытался отобразить это следующим образом:

<c:forEach var="results" items="${results}">
    ${results.heading}
</c:forEach>

Но выкинуло следующее исключение:

Вызвано: javax.servlet.ServletException: javax.servlet.jsp.JspTagException: не знаю, как перебирать предоставленные «элементы» в

Если я запишу результаты на своей странице обработчика, как это:

System.out.println( "\n\nthere are " + results.getColumnCount() + " columns in the result set" );
for( int i=0; i<results.getColumnCount(); i++ )
{
    System.out.println( results.getHeading(i) + " --> " + results.getType(i) );
}

Кажется, что журналирование нормально работает на сервере.

Ответы [ 3 ]

25 голосов
/ 04 февраля 2012

Причина: javax.servlet.ServletException: javax.servlet.jsp.JspTagException: не знаю, как перебирать предоставленные «элементы» в <forEach>

Это будетслучается, когда <c:forEach items> не ссылается на действительный объект, который он может перебрать.Объект должен быть Object[] (простой массив), Collection, Map, Iterator, Enumeration или String (см. Также исходный код ).Все остальное не может быть повторено по <c:forEach>.Ваш DetResults класс не является экземпляром ни одного из вышеупомянутых типов, поэтому он потерпит неудачу.

Ваш DetResults класс выглядит неправильно.Он выглядит в основном как один боб с набором всех свойств нескольких отдельных объектов.Это неправильно.Класс бина должен представлять не более одного объекта.Перепишите ваш класс DetResults, чтобы в итоге вы получили полноценную коллекцию javabeans:

List<DetResult> results = detDAO.fetchDetResults(paramBean);

, чтобы вы могли получить к ней доступ следующим образом:

<c:forEach items="${results}" var="result">
    ${result.heading}
    <c:forEach items="${result.data}" var="dataItem">
        ${dataItem}
    </c:forEach>
</c:forEach>

Если вы действительнонастаивайте на том, чтобы ваш бин DetResults был как есть, вы можете получить к нему доступ следующим образом:

<c:forEach begin="0" end="${results.columnCount}" varStatus="loop">
    ${results.headings[loop.index]}
    <c:forEach items="${results.data[loop.index]}" var="dataItem">
        ${dataItem}
    </c:forEach>
 </c:forEach>

См. также:


Не связано с конкретной проблемойатрибут <c:forEach var> неверен.Вы не должны давать ему то же имя, что и существующий объект в области видимости.Было бы только столкновение.Но это тема для нового вопроса, если вы не можете интерпретировать сообщение об ошибке.

1 голос
/ 04 февраля 2012

Вы должны иметь возможность перебирать заголовки

<tr>
<c:foreach var="heading" items="${results.headings}">
  <th>${heading}</th>
</c:foreach>
</tr>

И затем по данным ...

<c:foreach var="row" items="${results.data}">
  <tr>
  <c:foreach var="i" items="${row}">
    <td>${i}</td>
  </c:foreach>
  </tr>
</c:foreach>

Или что-то в этом духе? ​​

0 голосов
/ 27 декабря 2018

Проверьте этот код ниже в классе сервлетов:

request.setAttribute("productList", products);

И то же самое должно совпадать на странице JSP в <c:forEach:

<c:forEach var= "tempProducts" items= "${productList}">

ПРИМЕЧАНИЕ: "productList" имя должно точно соответствовать 1 пункту 1 и 2 тогда это будет.

Это сработало для меня.

...