在服务器端捕获生成的动态内容

2022-09-04 20:16:44

有没有办法在服务器端捕获生成的动态内容,并将该文件或字符串对象提供给servlet。

我们可以使用 JSP 生成动态内容,但我们无法访问服务器端生成的动态内容。一旦我们这样做,转发容器就会生成动态内容并将其发送到响应。

我需要访问服务器端生成的动态内容。

任何帮助将不胜感激。


答案 1

如果请求是幂等的(例如请求是幂等的),那么只需使用java.net.URL来获取JSP输出的输入流。例如:GET

InputStream input = new URL("http://localhost/context/page.jsp").openStream();

如果请求不是幂等的(例如请求),那么您需要创建一个过滤器,该过滤器使用PrintWriter的自定义实现包装,其中包含被覆盖的五种方法,其中您将输出复制到存储在会话中的某个缓冲区/构建器或本地磁盘文件系统的临时文件夹中,以便以后可以在后续请求中访问它。例如:POSTServletResponsewrite()

package mypackage;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class CopyResponseFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {
        // NOOP.
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException
    {
        // Set character encoding for better world domination.
        response.setCharacterEncoding("UTF-8");

        // Create copy writer.
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        CopyWriter copyWriter = new CopyWriter(new OutputStreamWriter(
            httpResponse.getOutputStream(), httpResponse.getCharacterEncoding()));

        // Filter request with response which is wrapped with new writer.
        chain.doFilter(request, wrapResponse(httpResponse, copyWriter));

        // Store the copy writer afterwards in session so that it's available in next request.
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        httpRequest.getSession().setAttribute("copyWriter", copyWriter);
    }

    public void destroy() {
        // NOOP.
    }

    private static HttpServletResponse wrapResponse
        (final HttpServletResponse response, final PrintWriter writer)
    {
        return new HttpServletResponseWrapper(response) {
            public PrintWriter getWriter() throws IOException {
                return writer;
            }
        };
    }

}

class CopyWriter extends PrintWriter {

    StringBuilder copy = new StringBuilder();

    public CopyWriter(Writer out) {
        super(out);
    }

    public void write(int c) {
        copy.append((char) c); // It is actually a char, not an int.
        super.write(c);
        super.flush();
    }

    public void write(char[] chars) {
        copy.append(chars);
        super.write(chars);
        super.flush();
    }

    public void write(char[] chars, int offset, int length) {
        copy.append(chars, offset, length);
        super.write(chars, offset, length);
        super.flush();
    }

    public void write(String string) {
        copy.append(string);
        super.write(string);
        super.flush();
    }

    public void write(String string, int offset, int length) {
        copy.append(string, offset, length);
        super.write(string, offset, length);
        super.flush();
    }

    public String getCopy() {
        return copy.toString();
    }

}

您可以通过访问会话中的任何 servlet 来访问后续请求的任何 servlet 中的最终输出(请注意,您无法在当前请求的任何 servlet 中访问它,因为处理它为时已晚):CopyWriter

CopyWriter copyWriter = (CopyWriter) request.getSession().getAttribute("copyWriter");
String outputOfPreviousRequest = copyWriter.getCopy();

请注意,您应该将此过滤器映射到覆盖感兴趣的JSP页面,因此不要在左右,否则它将在静态文件(css,js,图像等)上运行,这些文件也包含在同一JSP中。url-pattern/*

另请注意,同一会话中的多个请求将相互覆盖,这取决于您通过使用适当的或其他方式将其存储在会话中来区分这些请求,例如,以某种风格。url-patternMap<URL, CopyWriter>

希望这有帮助。


答案 2

据我所知,您的目标,您希望存储生成的内容。虽然我想不出任何理由这样做,但这是可能的。

您可以使用 和 创建 的包装器,覆盖某些方法并捕获将输出到浏览器的所有内容。FilterHttpServletResponsewrite

编辑:BalusC的答案是您需要的确切扩展,所以我不会详细介绍。