当前位置: 首页 > 知识库问答 >
问题:

在Weblogic 12c中以编程方式包含JSP的RequestDispatcher问题

滑弘扬
2023-03-14

我正在与以下情况作斗争:

在我们当前运行在Tomcat 7.0.64上的web应用程序中,我们借助自己的类CharrayWriterResponse实现了HttpServletResponseWrapper,通过Java成功地包含了一个JSP页面。

这样做的原因是我们将生成的超文本标记语言包装成AJAX响应所需的JSON。

依赖项:

<dependency>
     <groupId>javax</groupId>
     <artifactId>javaee-web-api</artifactId>
     <version>7.0</version>
     <scope>provided</scope>
</dependency>
<dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>jstl</artifactId>
     <version>1.2</version>
</dependency>

代码示例:

// somewhere in servlet doPost()/doGet()
try (PrintWriter out = response.getWriter()) {
     out.println(getJspAsJson(request, response));
}

private static String getJspAsJson(HttpServletRequest request, HttpServletResponse response) {
    String html = getHtmlByJSP(request, response, "WEB-INF/path/to/existing.jsp");
    Gson gson = new GsonBuilder().disableHtmlEscaping().create();
    return "{\"results\":" + gson.toJson(html) + "}";
}

public static String getHtmlByJSP(HttpServletRequest request, HttpServletResponse response, String jsp) {
     CharArrayWriterResponse customResponse = new CharArrayWriterResponse(response);
     request.getRequestDispatcher(jsp).include(request, customResponse);
     return customResponse.getOutput();
}

public class CharArrayWriterResponse extends HttpServletResponseWrapper {
    private final CharArrayWriter charArray = new CharArrayWriter();

    public CharArrayWriterResponse(HttpServletResponse response) {
        super(response);
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        // this is called ONLY in tomcat
        return new PrintWriter(charArray);
    }

    public String getOutput() {
        return charArray.toString();
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        // this is called ONLY in WebLogic
        return null; // don't know how to handle it
    }
}

提示:我没有考虑上述代码示例中的异常处理。

我必须将此应用程序迁移到WebLogic(12.2.1),但此解决方案不再有效。

到目前为止,我发现:

在调用请求后,在Tomcat中。getRequestDispatcher(jsp)。调用我的CharrayWriterResponse类的上述示例的include()。

在WebLogic中,不再调用getWriter(),这就是它不再工作的原因。

经过一些调试,我发现在WebLogic中,如果重写它,则只调用了而不是getWriter()<代码>getWriter()在Weblogic上不会被调用一次,因此Tomcat和Weblogic的底层实现必须有所不同。

问题是,对于getOutputStream(),我看不出有可能在单独的流或其他流中获得include()调用的响应,并将其转换为字符串以用于构建包含HTML的最终JSON。

是否有人已经解决了这个问题,并且可以提供一个工作解决方案,以编程方式将JSP与WebLogic结合起来?

有人知道实现我目标的其他解决方案吗?

感谢您的建议。

请参见此处的工作示例

我发现Tomcat和新的Weblogic解决方案之间的一个区别:对于后者,不再可能直接包含JSPF,而对于TomcatgetWriter()则是如此。

解决方案是将JSPF包装到JSP文件中。

共有3个答案

薛英卫
2023-03-14

这是我的更新和工作示例,如果在实现HttpServlet回应Wrapper时调用getOutputStream()而不是getWriter(),则如何以编程方式包含JSP文件:

public class MyServletOutputStream extends ServletOutputStream {

    private final BufferedOutputStream bufferedOut;

    public MyServletOutputStream(CharArrayWriter charArray) {
        this.bufferedOut = new BufferedOutputStream(new WriterOutputStream(charArray, "UTF-8"), 16384);
    }

    @Override
    public void write(int b) throws IOException {
        this.bufferedOut.write(b);
    }

    /**
     * This is needed to get correct full content without anything missing
     */
    @Override
    public void flush() throws IOException {
        if (this.bufferedOut != null) {
            this.bufferedOut.flush();
        }
        super.flush();
    }

    @Override
    public void close() throws IOException {
        this.bufferedOut.close();
        super.close();
    }

    @Override
    public boolean isReady() {
        return true;
    }

    @Override
    public void setWriteListener(WriteListener writeListener) {
    }
}

public class CharArrayWriterResponse extends HttpServletResponseWrapper {

    private final CharArrayWriter charArray = new CharArrayWriter();
    private ServletOutputStream servletOutputStream;

    public CharArrayWriterResponse(HttpServletResponse response) {
        super(response);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (servletOutputStream == null) {
            servletOutputStream = new MyServletOutputStream(this.charArray);
        }
        return servletOutputStream;
    }

    public String getOutputAndClose() {
        if (this.servletOutputStream != null) {
            try {
                // flush() is important to get complete content and not last "buffered" part missing
                this.servletOutputStream.flush()
                return this.charArray.toString();
            } finally {
                this.servletOutputStream.close()
            }
        }
        throw new IllegalStateException("Empty (null) servletOutputStream not allowed");
    }

    // not necessary to override getWriter() if getOutputStream() is used by the "application server".
}

// ...somewhere in servlet process chain e.g. doGet()/doPost()
// request/response The original servlet request/response object e.g. from doGet/doPost(HttpServletRequest request, HttpServletResponse response)
CharArrayWriterResponse customResponse = new CharArrayWriterResponse(response);
request.getRequestDispatcher("/WEB-INF/path/to/existing.jsp").include(request, customResponse);
String jspOutput = customResponse.getOutputAndClose();
// do some processing with jspOut e.g. wrap inside JSON

// customResponse.getOutputStream() is already closed by calling getOutputAndClose()
东方弘壮
2023-03-14

由于我不知道如何将多行代码放入注释中,我只是把它放在这里。我可以通过在MyServletOutputStream类中覆盖flush()方法来解决这个问题:

// inside MyServletOutputStream class
@Override
public void flush() throws IOException {
    if (this.bufferedOut != null) {
        this.bufferedOut.flush();
    }
    super.flush();
}
微生自怡
2023-03-14

我做到了:

@Override
public ServletOutputStream getOutputStream() throws IOException {
    // this is called ONLY in WebLogic
    // created a custom outputstream that wraps your charArray
    return new CustomOutputStream(this.charArray);
}

// custom outputstream to wrap charArray writer
class CustomOutputStream extends ServletOutputStream {

    private WriterOutputStream out;

    public CustomOutputStream(CharArrayWriter writer) {
        // WriterOutputStream has a constructor without charset but it's deprecated, so change the UTF-8 charset to the one you use, if needed
        this.out = new WriterOutputStream(writer, "UTF-8");
    }

    @Override
    public boolean isReady() {
        return true;
    }

    @Override
    public void setWriteListener(WriteListener writeListener) {
    }

    @Override
    public void write(int b) throws IOException {
        this.out.write(b);
        this.out.flush(); // it doesn't work without flushing
    }
}

我使用了apache Commons-io中的WriterOutputStream,因此我必须在我的pom.xml中包含:

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.5</version>
</dependency>

我不知道您的jsp文件中有什么内容,但我已经用一个简单的文件进行了测试,我相信它是有效的。我的jsp文件:

<b>Hello world</b>

<p>testing</p>

<ul>test
<li>item</li>
<li>item2</li>
</ul>

输出(在浏览器中访问servlet时):

{"results":"<b>Hello world</b>\n\n<p>testing</p>\n\n<ul>test\n<li>item</li>\n<li>item2</li>\n</ul>"}
 类似资料:
  • 问题内容: 因此,我创建了一个名为CustomTitlebarActivity的Activity子类。本质上,我的应用程序中的每个主要活动都将具有一个自定义标题栏,该标题栏具有许多常用功能,例如主页按钮,标题,搜索按钮等。在当前的实现中,我仍然在布局XML中显式使用include语句每个CustomTitlebarActivity: 我似乎应该能够在CustomTitlebarActivity中执

  • 我正在使用J2EE(使用spring和JSP)建立一个网站。我有像client.jsp和user.jsp的多页。每一页都有一个页眉、一个内容和一个页脚。 因此,我想做的是在每个jsp文件(客户机或用户)中包含页眉和页脚,但每个文件都有一个特定的页眉和脚注。比方说,header_client。jsp和header_footer.jsp。 为了包括这个,我正在做的: 但是,如果此标头不存在,我想加载一

  • 问题内容: 有一个网页,我想从中检索某个字符串。为此,我需要登录,单击一些按钮,填充文本框,单击另一个按钮-然后出现字符串。 如何编写Java程序以自动执行此操作?是否有用于此目的的有用库? 谢谢 问题答案: 试试HtmlUnit HtmlUnit是“用于Java程序的GUI更少的浏览器”。它为HTML文档建模,并提供一个API,使您可以调用页面,填写表单,单击链接等,就像在“常规”浏览器中一样。

  • 问题内容: 有没有一种方法可以在Windows中创建链接? 我发现使用的样本或必须下载的样本。 我需要一个简单的解决方案。那可能吗? 问题答案: 好了,我不得不使用创建快捷方式的方法,但是实际上我需要的是一个文件夹,但是会创建一个。 最终我用来创建。

  • 问题内容: 我想在头部分中以编程方式添加StyleSheets,但是我看到的示例之一似乎需要多行代码才能仅添加一个样式表,即使我可能需要很多: 示例代码: 我也使用方法,但是它也不起作用。对象null抛出了错误。 我也使用了和东西,但是它们抛出了文字错误,这是我认为的常见错误。 我使用此代码: 起初它起作用,但是当我更改页面时,它停止工作。 我正在使用“母版页”,并且正在文件中编写这些代码,也有人