2011-07-20 32 views
7

Tôi có một JSP mà cần phải in một số văn bản được sản xuất bằng cách lấy vòng lặp và nuôi nó đến một đối tượng khác (Spring đậu), một cái gì đó như:Gọi một phương thức với tham số bên trong vòng lặp JSTL

<c:forEach var="myVar" items="${myVars}"> 
    <c:out value="anotherObject.getFoo(myVar)"/> 
</c:forEach> 

Rõ ràng mã trên không hợp lệ vì nhà khai thác JSTL . chỉ cho phép các yêu cầu ít tham số. Tôi có thể thấy các giải pháp sau đây để các vấn đề:

1) scriptlets

<c:forEach var="myVar" items="${myVars}"> 
    <% 
    SomeType myVar = (SomeType) pageContext.getAttribute("myVar"); 
    SomeOtherType anotherObject = (SomeOtherType) pageContext.getAttribute("anotherObject"); 
    YetAnotherType result = anotherObject.getFoo(myVar); 
    pageContext.setAttribute("result", result); 
    %> 
    <c:out value="${result}"/> 
</c:forEach> 

Các con rõ ràng ở đây là JSP đang ô nhiễm và xấu xa nói chung.

2) Viết thẻ thực hiện bất kỳ điều gì được thực hiện bên trong tập lệnh. Ví dụ điển hình về kỹ thuật quá mức, yuck!

3) Phân hủy một bộ sưu tập của myVars và thay thế mỗi myVar với một dynamic proxy, InvocationHandler trong số đó sẽ bổ sung thêm phương pháp tham số-ít hơn để làm cho tất cả các cuộc gọi qua getFoo()anotherObject. Tất cả điều đó sẽ được thực hiện trong bộ điều khiển để JSP luôn sạch sẽ và myVar vẫn giữ nguyên. Nhưng ở mức giá nào?

Tôi không thể thêm phương thức .getFoo() vào myVar vì phương thức này không phù hợp và sẽ phá vỡ sự phân tách mối quan tâm.

Dường như các tham số truyền sẽ có thể có trong JSP/EL 2.2, nhưng tôi đang sử dụng Tomcat 6.0.29 chỉ bao gồm API EL 2.1.

Câu hỏi: ai có thể đề xuất cách tiếp cận sạch nhất cho tình huống này?

Trả lời

2

Đây là cách tôi đã thực hiện nó ở cuối.

Thay vì chuyển bộ sưu tập SomeType trường hợp, tôi đang chuyển một bản đồ. Các khóa bản đồ giống nhau là SomeType s và các giá trị là các thể hiện của lớp bên trong của trình điều khiển cụ thể, hãy gọi nó là SomeTypeSupplement.

SomeTypeSupplement thêm cần thiết no-arg getters và nối mọi thứ lại với nhau. JSP bây giờ lặp qua các mục bản đồ và có thể lấy dữ liệu qua JSTL.

Bằng cách này tôi tránh Proxy phép thuật, TLD không cần thiết, giữ cho JSP gọn gàng và hợp lý loại an toàn.

1

Nếu bạn không thể tuân theo tập lệnh (phương án 1), tôi sẽ tạo thẻ tùy chỉnh cho nó (tùy chọn 2 của bạn) hoặc chức năng EL tùy chỉnh. Tôi không đồng ý rằng đó là "quá kỹ thuật", nó sử dụng các công cụ có sẵn cho mục đích của họ.

Phương án 3 của bạn, tuy nhiên, tôi không thích. Nếu bất cứ điều gì, đó là over-kỹ thuật cộng với nó sẽ làm cho hệ thống của bạn không cần thiết phức tạp và khó khăn hơn cho những người khác để làm theo. Tuân theo ý định của các thông số kỹ thuật và tiêu chuẩn bạn đang làm việc bên trong. Đừng làm mọi việc khó khăn hơn hoặc phức tạp hơn vì lợi ích của nó.

+3

Nếu viết một thẻ JSP cho mỗi cuộc gọi phương thức đơn lẻ không quá kỹ thuật, thì tôi không biết kỹ thuật quá mức là gì. Tôi không nói tùy chọn # 3 là tốt/ưa thích, nhưng không phải là # 2. – mindas

+0

Vâng, nếu bạn đang có rất nhiều trường hợp bạn phải gọi một cách rõ ràng các phương thức trong JSP: s, thì tôi đề nghị bạn cải thiện mẫu MVC của bạn và nỗ lực tạo ra một lớp Mô hình sạch hơn chỉ chứa dữ liệu. Sau đó di chuyển bất kỳ logic vào lớp điều khiển của bạn. – pap

+0

Đối tượng myVar là một ví dụ chính xác về những gì bạn gọi là Mô hình (đối tượng chỉ chứa dữ liệu lưu giữ dữ liệu trong trường hợp này). Tuy nhiên dữ liệu tôi cần để hình dung là đến từ nguồn hoàn toàn khác nhau ("' anotherObject' ") và yêu cầu lớp mô hình này. Đề nghị của bạn để di chuyển logic đến lớp điều khiển là gần với tùy chọn # 3 mà tôi đề nghị và bạn nói đó là một ý tưởng tồi. – mindas

1

Tại sao không chỉ soạn danh sách đối tượng trong mã Java phụ trợ của bạn và sau đó chỉ sử dụng JSP để hiển thị nó?

+0

Tôi không nghĩ rằng bạn đã hiểu vấn đề tôi đang gặp phải. '$ {myVars}' đã đề cập đến một danh sách các đối tượng. – mindas

0

Một tùy chọn khác là sử dụng Velocity. Nó đẹp hơn nhiều so với jstl.

+1

Bỏ phiếu cho một giải pháp thay thế sáng tạo (và ưu tiên cho cá nhân tôi) nhưng sau đó chúng tôi không thể luôn chọn cách chúng tôi được phép phục vụ lượt xem – darkpbj

7

Một đơn giản Java chỉ "lừa-sửa chữa" mà làm việc trong phiên bản JSTL cũ, quá, và không yêu cầu thêm taglibs/config/phụ thuộc/khuôn khổ vv là để "bọc" các chức năng bạn muốn gọi từ JSTL trong một lớp kéo dài từ lớp Map và ghi đè phương thức get() của nó.

Ví dụ tối thiểu, ví dụ: muốn gọi Math.sin() chức năng từ JSTL, bạn sẽ xác định một lớp:

public class Sine extends HashMap<Double, Double> { 
    private static final long serialVersionUID = 1L; // Avoids compiler-warning 

    @Override 
    public Double get(Object arg) { 
     Double x = (Double) arg; 
     return Math.sin(x); 
    } 
} 

Sau đó, trong hành động của bạn thực hiện() phương pháp, bạn cần làm:

... 
request.setAttribute("sine", new Sine()); 
... 

Sau đó, trong jsp bạn có thể nói:

${sine[0.75]} 

để tính giá trị Math.sin(0.75)

JSTL sẽ coi sin biến là Map, nhưng bạn có thể tính toán và trả lại bất kỳ thứ gì bạn thích từ phương thức get().

Tôi đoán nó được một chút tham gia nhiều hơn nếu bạn có nhiều hơn một đối số cho chức năng của bạn, nhưng không nên có cách giải quyết cho rằng, quá :)

+1

Cách tiếp cận thú vị, cảm ơn bạn đã chia sẻ! – mindas

+1

Rất đẹp và khéo léo, cảm ơn rất nhiều. cho những người mới trong các chất liệu này modelAndView.addObject ("sin", Sine mới()); là phiên bản MVC mùa xuân tương đương của request.setAttribute ("sine", new Sine()); – HaMi

1

Muốn thêm một lời nhận xét để cuối cùng (theo thời gian) câu trả lời của Rop, nhưng thiếu "danh tiếng", vì vậy ở đây tôi có một câu trả lời. Tôi đã có ý tưởng tương tự với một bản đồ như vậy, nhưng đã cố gắng làm cho nó dễ sử dụng hơn, có giao diện "DynamicMap", DynamicMapCalculator và cho phép bạn bao bọc bất kỳ cuộc gọi phương thức nào vào một bản đồ như vậy (mà không cần phải thực hiện thực hiện bản đồ mới mọi lúc, chỉ cần sử dụng instantiation class ẩn danh).

Đây sẽ là chủ đề, nếu bạn quan tâm: A qu. of style: dynamic map JSTL hack to work around missing parameter function calls

Và tôi sẽ quan tâm đến ý kiến ​​đó: là một cái gì đó này, bạn có thể làm mà không có lương tâm xấu?

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