21

次のような Java Bean があります。

class Person {
  int age;
  String name;
}

JSP でこれらの Bean のコレクションを反復処理し、各人物を HTML テーブルの行に表示し、テーブルの最後の行にすべての年齢の合計を表示したいと考えています。

テーブル行を生成するコードは次のようになります。

<c:forEach var="person" items="${personList}">
  <tr><td>${person.name}<td><td>${person.age}</td></tr>
</c:forEach>

ただし、スクリプトレットコードに頼らずに最終行に表示される年齢の合計を計算する方法を見つけるのに苦労しています。何か提案はありますか?

4

7 に答える 7

44

注:回答を組み合わせて包括的なリストを作成してみました。必要に応じてクレジットを与えるために、適切な場所で名前を挙げました。

この問題を解決するには多くの方法があり、それぞれに長所と短所があります。

純粋な JSP ソリューション

ScArcher2 が上で述べたように、この問題に対する非常に簡単でシンプルな解決策は、次のように JSP に直接実装することです。

<c:set var="ageTotal" value="${0}" />
<c:forEach var="person" items="${personList}">
  <c:set var="ageTotal" value="${ageTotal + person.age}" />
  <tr><td>${person.name}<td><td>${person.age}</td></tr>
</c:forEach>
${ageTotal}

このソリューションの問題点は、スクリプトレットを導入した方がよいほど JSP が混乱することです。ページを見ているすべての人が提示された初歩的なロジックに従うことができると予想される場合、それは良い選択です.

純粋な EL ソリューション

すでに EL 3.0 (Java EE 7 / Servlet 3.1) を使用している場合は、ストリームとラムダの新しいサポートを使用してください。

<c:forEach var="person" items="${personList}">
  <tr><td>${person.name}<td><td>${person.age}</td></tr>
</c:forEach>
${personList.stream().map(person -> person.age).sum()}

JSP EL 関数

JSP にスクリプトレット コードを導入せずに合計を出力する別の方法は、EL 関数を使用することです。EL 関数を使用すると、パブリック クラスで public static メソッドを呼び出すことができます。たとえば、コレクションを反復処理して値を合計したい場合は、PersonUtils などのパブリック クラスで sum(List people) というパブリック静的メソッドを定義できます。tld ファイルに次の宣言を配置します。

<function>
  <name>sum</name>
  <function-class>com.example.PersonUtils</function-class>
  <function-signature>int sum(java.util.List people)</function-signature>
</function> 

JSP 内で次のように記述します。

<%@ taglib prefix="f" uri="/your-tld-uri"%>
...
<c:out value="${f:sum(personList)}"/>

JSP EL 関数にはいくつかの利点があります。これらを使用すると、特定の UI (カスタム タグ ライブラリ) にコーディングする必要なく、既存の Java メソッドを使用できます。また、コンパクトであり、プログラミングに慣れていない人を混乱させることはありません。

カスタムタグ

さらに別のオプションは、独自のカスタム タグをロールすることです。このオプションにはほとんどのセットアップが含まれますが、本質的に探していると思われるものを提供します。スクリプトレットはまったくありません。シンプルなカスタム タグを使用するための優れたチュートリアルは、http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701にあります。

関連する手順には、TagSupport のサブクラス化が含まれます。

public PersonSumTag extends TagSupport {

   private List personList;

   public List getPersonList(){
      return personList;
   }

   public void setPersonList(List personList){
      this.personList = personList;
   }

   public int doStartTag() throws JspException {
      try {
        int sum = 0;
        for(Iterator it = personList.iterator(); it.hasNext()){
          Person p = (Person)it.next();
          sum+=p.getAge();
        } 
        pageContext.getOut().print(""+sum);
      } catch (Exception ex) {
         throw new JspTagException("SimpleTag: " + 
            ex.getMessage());
      }
      return SKIP_BODY;
   }
   public int doEndTag() {
      return EVAL_PAGE;
   }
}

tld ファイルでタグを定義します。

<tag>
   <name>personSum</name>
   <tag-class>example.PersonSumTag</tag-class>
   <body-content>empty</body-content>
   ...
   <attribute>
      <name>personList</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>java.util.List</type>
   </attribute>
   ...
</tag>

JSP の上部で taglib を宣言します。

<%@ taglib uri="/you-taglib-uri" prefix="p" %>

次のタグを使用します。

<c:forEach var="person" items="${personList}">
  <tr><td>${person.name}<td><td>${person.age}</td></tr>
</c:forEach>
<p:personSum personList="${personList}"/>

表示タグ

前述の zmf のように、display タグを使用することもできますが、適切なライブラリを含める必要があります。

http://displaytag.sourceforge.net/11/tut_basic.html

于 2008-09-19T17:39:59.673 に答える
5

すべての年齢を合計しようとしていますか?

コントローラーで計算し、結果をjspに表示するだけです。

カスタム タグを記述して計算を行うことができます。

このようにjstlを使用してjspで計算できます。

<c:set var="ageTotal" value="${0}" />
<c:forEach var="person" items="${personList}">
  <c:set var="ageTotal" value="${ageTotal + person.age}" />
  <tr><td>${person.name}<td><td>${person.age}</td></tr>
</c:forEach>
${ageTotal}
于 2008-09-19T15:44:07.707 に答える
3

表示タグを確認してください。http://displaytag.sourceforge.net/11/tut_basic.html

于 2008-09-19T15:40:11.943 に答える
1

ScArcher2 には最も簡単なソリューションがあります。できるだけコンパクトなものが必要な場合は、「合計」関数を含むタグ ライブラリを作成できます。何かのようなもの:

class MySum {
public double sum(List list) {...}
}

TLD で:

<function>
<name>sum</name>
<function-class>my.MySum</function-class>
<function-signature>double sum(List)</function-signature>
</function>

JSP には、次のようなものがあります。

<%@ taglib uri="/myfunc" prefix="f" %>

${f:sum(personList)}
于 2008-09-19T15:57:04.100 に答える
0

JSP ではなくコントローラで Totals/ またはその他の集計を計算することを強くお勧めします。

JSP や JSTL でやりすぎるのではなく、Java コードと MVC アプローチ (Spring MVC フレームワークなど) を使用します。これらの言語で重要な計算を行うと、弱くて遅くなり、JSP ページがかなり不明確になります。

例:

class PersonList_Controller implements Controller {
    ...
    protected void renderModel (List<Person> items, Map model) {
        int totalAge = 0;
        for (Person person : items) {
            totalAge += person.getAge();
        }
        model.put("items", items);
        model.put("totalAge", totalAge);
    }
}

設計上の意思決定 - 合計が必要な場合は、来月には平均、中央値、標準偏差が必要になるように延長される可能性があります。

JSTL の計算と要約は、合計を取得するだけで、ほとんどまとまりません。JSTL のその他の要約要件を満たす必要がありますか? 答えは NO だと思います。したがって、正しい設計上の決定は、コントローラーで計算することです。これは、同等/より単純で、間違いなくより妥当な要件が拡張可能であるためです。

于 2013-03-30T05:59:02.000 に答える
0

少しハックですが、コントローラー コードで、合計を含むダミーの Person オブジェクトを作成するだけで済みます。

オブジェクトをどのように取得していますか? HTML では<TFOOT>要素を設定できます。この要素はすべてのデータの最後に配置されます。したがって、Person オブジェクトとは別に合計を設定し、JSP ページで計算することなくそのままページに出力できます。

于 2008-09-19T15:39:10.150 に答える
0

次に従ってJSTLを使用してコレクションを反復処理できます

<c:forEach items="${numList}" var="item">
      ${item}
</c:forEach>

それが次でできる地図なら

<c:forEach items="${numMap}" var="entry">
  ${entry.key},${entry.value}<br/>
</c:forEach>
于 2012-05-04T03:34:11.867 に答える