2009-07-27 27 views
6

Tôi đang chuyển đổi sang hình ảnh và đầu ra PDF. Tôi cần một tài liệu HTML đầu vào được tạo ra bởi các ứng dụng JSP của chúng tôi. Về cơ bản, tôi cần render sản phẩm đầu ra cuối cùng của một ứng dụng dựa trên JSP tới một String hoặc bộ nhớ và sau đó sử dụng chuỗi đó để xử lý khác.Trình biên dịch JSP thành chuỗi hoặc trong bộ nhớ được sắp xếp bằng Tomcat/Websphere

Một số cách mà tôi có thể gọi trình kết xuất JSP để nhận nội dung HTML cuối cùng thường được xuất cho người dùng là gì? Lý tưởng nhất, tôi đang tìm một cái gì đó sẽ làm việc cho nhiều máy chủ ứng dụng như websphere. Nhưng một cái gì đó là Tomcat cụ thể cũng sẽ làm việc.

Có một vài cách tiếp cận khác nhau khác nhau, nhưng tôi nghĩ việc hiển thị JSP (có thể bao gồm các JSP phụ) là cách tiếp cận tốt nhất.

Đường dẫn tùy chọn mà tôi muốn tránh xa.

  1. Tôi có thể thực hiện yêu cầu mạng tới trang bằng API Socket và sau đó đọc kết quả cuối cùng được hiển thị từ trang cụ thể đó. Đây có lẽ là lựa chọn tốt nhất tiếp theo, nhưng chúng tôi làm việc trên nhiều máy chủ và JVM, nhắm mục tiêu trang tôi cần sẽ phức tạp.

  2. Sử dụng bộ lọc để có được kết quả trang cuối cùng đó. Điều này Ok nhưng tôi đã luôn luôn có vấn đề với các bộ lọc và ngoại lệ bất hợp pháp. Nó dường như không bao giờ hoạt động 100% theo cách tôi cần.

Dường như điều này đơn giản. Trình biên dịch JSP về cơ bản chỉ là một thư viện để phân tích cú pháp một tài liệu JSP đầu vào và các phần phụ và sau đó xuất ra một số nội dung HTML. Tôi muốn gọi quá trình đó thông qua mã Java. Trên máy chủ và có thể là một ứng dụng giao diện điều khiển độc lập.

Trả lời

6

Đây là một vấn đề khó chịu hết sức, tôi phải xử lý một vài lần và tôi chưa bao giờ tìm được giải pháp thỏa đáng.

Vấn đề cơ bản là API servlet không có ích gì ở đây, vì vậy bạn phải đánh lừa nó. Giải pháp của tôi là viết một lớp con của HttpServletResponseWrapper để ghi đè lên các phương thức getWriter() và getOutput() và nắm bắt dữ liệu vào một bộ đệm. Sau đó bạn chuyển tiếp() yêu cầu của bạn tới URI của JSP mà bạn muốn chụp, thay thế phản hồi trình bao bọc của bạn cho phản hồi ban đầu. Sau đó, bạn trích xuất dữ liệu từ bộ đệm, thao tác nó và ghi kết quả cuối cùng về phản hồi ban đầu.

Dưới đây là mã của tôi mà thực hiện điều này:

public class CapturingResponseWrapper extends HttpServletResponseWrapper { 

    private final OutputStream buffer; 

    private PrintWriter writer; 
    private ServletOutputStream outputStream; 

    public CapturingResponseWrapper(HttpServletResponse response, OutputStream buffer) { 
     super(response); 
     this.buffer = buffer; 
    } 

    @Override 
    public ServletOutputStream getOutputStream() { 
     if (outputStream == null) { 
      outputStream = new DelegatingServletOutputStream(buffer); 
     } 
     return outputStream; 
    } 

    @Override 
    public PrintWriter getWriter() { 
     if (writer == null) { 
      writer = new PrintWriter(buffer); 
     } 
     return writer; 
    } 

    @Override 
    public void flushBuffer() throws IOException { 
     if (writer != null) { 
      writer.flush(); 
     } 
     if (outputStream != null) { 
      outputStream.flush(); 
     } 
    } 

} 

Các mã để sử dụng nó có thể là một cái gì đó như thế này:

HttpServletRequest originalRequest = ... 
HttpServletResponse originalResponse = ... 

ByteArrayOutputStream bufferStream = new ByteArrayOutputStream(); 
CapturingResponseWrapper responseWrapper = new CapturingResponseWrapper(originalResponse, bufferStream); 

originalRequest.getRequestDispatcher("/my.jsp").forward(originalRequest, responseWrapper); 

responseWrapper.flushBuffer(); 
byte[] buffer = bufferStream.toByteArray(); 
// now use the data 

Nó rất xấu xí, nhưng đó là giải pháp tốt nhất mà tôi đã tìm thấy. Trong trường hợp bạn đang phân vân, đáp ứng của trình bao bọc phải chứa đáp ứng ban đầu vì đặc tả servlet nói rằng bạn không thể thay thế một đối tượng yêu cầu hoặc đáp ứng hoàn toàn khác khi bạn chuyển tiếp, bạn phải sử dụng các bản gốc hoặc các phiên bản được bao bọc của chúng.

+0

+1 Hãy đánh bại tôi. –

+0

Tôi có cảm giác mọi người đều có cùng một giải pháp khủng khiếp. – skaffman

+0

Đó là một cách tiếp cận tốt. Loại giống như phương pháp định hướng 'lọc'. Nhưng vấn đề duy nhất với điều này, có hai vấn đề. 1. Bạn không thể chạy điều này như một hệ thống độc lập. Ví dụ.bạn không thể làm: chính() {compileJSP()} 2. Nếu bạn sử dụng mã này trong mã bộ lọc, một số máy chủ applciation đang đánh giá tình trạng của requestwrapper và tôi có xu hướng nhận được ngoại lệ bất hợp pháp và không bao giờ có thể JSP để render thành một chuỗi (về cơ bản khi tôi làm điều này nó không bao giờ đơn giản). Nhưng, đó là một giải pháp tốt. –

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