2008-09-19 30 views
16

tôi có một chương trình Java như thế này:Tính tổng của tất cả các số trong c: foreach vòng lặp

class Person { 
    int age; 
    String name; 
} 

Tôi muốn để lặp qua một bộ sưu tập của những hạt cà phê trong một JSP, cho thấy mỗi người trong một Hàng của bảng HTML và trong hàng cuối cùng của bảng tôi muốn hiển thị tổng số tất cả các độ tuổi.

Mã để tạo ra các hàng bảng sẽ trông giống như thế này:

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

Tuy nhiên, tôi đang đấu tranh để tìm thấy một cách để tính toán tổng số tuổi sẽ được hiển thị ở hàng thức mà không cần mã scriptlet, bất kỳ đề xuất nào?

+0

Bạn có đang thêm tất cả độ tuổi và hiển thị ở hàng cuối cùng không? – ScArcher2

Trả lời

36

Lưu ý: tôi đã cố gắng kết hợp các câu trả lời để làm cho một danh sách toàn diện. Tôi đã đề cập đến tên khi thích hợp để cung cấp tín dụng khi đến hạn.

Có rất nhiều cách để giải quyết vấn đề này, với những ưu/nhược điểm gắn liền với mỗi:

tinh khiết JSP Giải pháp

Như ScArcher2 đề cập ở trên, một giải pháp rất dễ dàng và đơn giản cho vấn đề là để thực hiện nó trực tiếp trong JSP như sau:

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

Vấn đề với giải pháp này là JSP trở nên khó hiểu đến mức bạn cũng có thể có các tập bản giới thiệu. Nếu bạn dự đoán rằng tất cả mọi người nhìn vào trang sẽ có thể làm theo logic thô sơ, nó là một lựa chọn tốt.

tinh khiết EL giải pháp

Nếu bạn đã có trên EL 3.0 (Java EE 7/Servlet 3.1), sử dụng hỗ trợ mới cho streams and lambdas:

<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 Chức năng

Một cách khác để xuất tổng số mà không đưa mã scriplet vào JSP của bạn là sử dụng hàm EL. Các hàm EL cho phép bạn gọi một phương thức tĩnh công cộng trong một lớp công khai. Ví dụ, nếu bạn muốn lặp qua bộ sưu tập của bạn và tổng hợp các giá trị bạn có thể định nghĩa một phương thức tĩnh công cộng được gọi là tổng (Liệt kê mọi người) trong một lớp công khai, có lẽ được gọi là PersonUtils. Trong tập tin TLD của bạn, bạn sẽ đặt các tuyên bố sau đây:

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

Trong JSP của bạn, bạn sẽ viết:

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

JSP EL Chức năng có một số lợi ích. Chúng cho phép bạn sử dụng các phương thức Java hiện có mà không cần mã vào một giao diện người dùng cụ thể (Thư viện thẻ tùy chỉnh). Chúng cũng nhỏ gọn và sẽ không gây nhầm lẫn cho một người không định hướng lập trình.

Tuỳ chỉnh Tag

Tuy nhiên, tùy chọn khác là để cuộn thẻ tùy chỉnh của riêng bạn. Tùy chọn này sẽ liên quan đến việc thiết lập nhiều nhất nhưng sẽ cung cấp cho bạn những gì tôi nghĩ rằng bạn đang esentially tìm kiếm, absolutly không có scriptlets.Một hướng dẫn tốt đẹp cho sử dụng các thẻ tùy chỉnh đơn giản có thể được tìm thấy tại http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags5.html#74701

Các bước tham gia bao gồm subclassing 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; 
    } 
} 

Xác định thẻ trong một tập tin 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> 

Khai báo taglib trên đầu JSP của bạn:

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

và sử dụng thẻ:

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

Display Tag

Như zmf đề cập trước đó, bạn cũng có thể sử dụng thẻ hiển thị, mặc dù bạn sẽ cần phải bao gồm các thư viện thích hợp:

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

+0

Tính tổng số trong bộ điều khiển - không phải trong JSP - thực sự rất thích hợp. Sử dụng một khung MVC, ví dụ như Spring, thay vì cố gắng làm quá nhiều trong JSP hoặc JSTL. –

0

Đó là một chút hacky, nhưng trong mã điều khiển của bạn, bạn chỉ có thể tạo một đối tượng Người giả với tổng số trong đó!

Bạn đang truy xuất các đối tượng của mình bằng cách nào? HTML cho phép bạn thiết lập một phần tử <TFOOT> sẽ nằm ở dưới cùng của bất kỳ dữ liệu nào bạn có, do đó bạn chỉ có thể thiết lập tổng số riêng biệt với các đối tượng Person và xuất nó trên trang như không có bất kỳ tính toán nào trên trang JSP.

3

Bạn đang cố gắng thêm tất cả các độ tuổi?

Bạn có thể tính toán nó trong bộ điều khiển của mình và chỉ hiển thị kết quả trong jsp.

Bạn có thể viết thẻ tùy chỉnh để thực hiện phép tính.

Bạn có thể tính toán nó trong jsp bằng cách sử dụng jstl như thế này.

<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} 
1

ScArcher2 có đơn giản nhất solution. Nếu bạn muốn một cái gì đó nhỏ gọn nhất có thể, bạn có thể tạo một thư viện thẻ với một hàm "tổng hợp" trong đó. Một cái gì đó như:

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

Trong TLD của bạn:

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

Trong JSP của bạn, bạn muốn có một cái gì đó như:

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

${f:sum(personList)} 
+0

Không linh hoạt - hàm tổng hoặc hàm tổng() có nghĩa là tính toán, không thể xác định được. Hoặc bạn đã đi một chặng đường dài để thực hiện một nhà điều hành mục đích duy nhất, hoặc bạn phải đi xa hơn và nhận được hacky với sự phản ánh để làm cho nó linh hoạt. –

+0

Câu trả lời ngắn và chính xác: tính toán tóm tắt trong Bộ điều khiển, không phải trong JSP. –

0

bạn có thể lặp trên một bộ sưu tập sử dụng JSTL theo sau

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

nếu nó là một bản đồ mà bạn có thể làm trên Totals sau

<c:forEach items="${numMap}" var="entry"> 
    ${entry.key},${entry.value}<br/> 
</c:forEach> 
0

Tính/hoặc tóm tắt khác trong bộ điều khiển - không có trong JSP - thực sự mạnh mẽ thích hợp hơn.

Sử dụng mã Java & cách tiếp cận MVC, ví dụ: khuôn khổ Spring MVC, thay vì cố gắng thực hiện quá nhiều trong JSP hoặc JSTL; thực hiện tính toán quan trọng bằng các ngôn ngữ này là yếu kém & chậm và làm cho các trang JSP của bạn kém rõ ràng hơn nhiều.

Ví dụ:

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

Thiết kế ra quyết định khôn ngoan - bất cứ nơi nào tổng cộng là cần thiết, có thể hình dung vào tháng tới được mở rộng để yêu cầu một Trung bình, một trung bình, độ lệch chuẩn.

Tính toán JSTL & tóm tắt không được giữ chặt với nhau, chỉ vừa mới nhận được tổng số. Bạn có thực sự muốn đáp ứng thêm bất kỳ yêu cầu tóm tắt nào trong JSTL không? Tôi tin rằng câu trả lời là KHÔNG - và do đó quyết định thiết kế chính xác là để tính toán trong Bộ điều khiển, như nhau/đơn giản hơn và chắc chắn hơn các yêu cầu hợp lý có thể mở rộng.

Các vấn đề liên quan