c:forEach ループ内のすべての数値の合計を計算します。
質問
次のような 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>
ただし、最後の行に表示される年齢の合計を計算する方法を見つけるのに苦労しています。 スクリプトレットコードに頼らずに, 、 助言がありますか?
解決
注記: 回答を組み合わせて包括的なリストを作成してみました。クレジットを記載する必要がある場合は、適切な場合に名前を言及しました。
この問題を解決するには多くの方法があり、それぞれに長所と短所があります。
純粋な 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 にスクリプト コードを導入せずに合計を出力するもう 1 つの方法は、EL 関数を使用することです。EL 関数を使用すると、パブリック クラスでパブリック静的メソッドを呼び出すことができます。たとえば、コレクションを反復処理して値を合計したい場合は、パブリック クラス (おそらく 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 が前述したように、適切なライブラリを含める必要がありますが、表示タグを使用することもできます。
他のヒント
すべての年齢を合計しようとしていますか?
コントローラーで計算し、その結果を 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}
表示タグを確認してください。 http://displaytag.sourceforge.net/11/tut_basic.html
ScArcher2 には最も単純な機能があります。 解決. 。できるだけコンパクトなものが必要な場合は、「sum」関数を含むタグ ライブラリを作成できます。何かのようなもの:
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)}
これは少しハック的ですが、コントローラー コード内で、合計を含むダミーの Person オブジェクトを作成するだけです。
オブジェクトをどのように取得していますか?HTML を使用すると、 <ティーフット> この要素は、手持ちのデータの一番下に位置するため、 Person オブジェクトとは別に合計を設定し、JSP ページで計算を行わずにそのままページに出力できます。
次のように、JSTL を使用してコレクションを反復処理できます。
<c:forEach items="${numList}" var="item">
${item}
</c:forEach>
地図の場合は次のようにできます
<c:forEach items="${numMap}" var="entry">
${entry.key},${entry.value}<br/>
</c:forEach>
Totals やその他の集計は、JSP ではなくコントローラーで計算することを強くお勧めします。
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 でさらに概要要件を満たすつもりですか?私は、答えはノーであると信じています。したがって、正しい設計上の決定は、同様に/より単純で、間違いなくより妥当な要件を拡張可能であるとして、コントローラーで計算することです。