java - J2EE : Understanding isCommitted and Filters under this scenario

标签 java servlets

我正在开发一个过滤器,如果请求中涉及“转发”,则此代码将无法执行/response.write。但它对于简单地将 HTML 内容传送给用户的基本 servlet 来说效果很好。如何使用此代码解决“转发”问题。

例如,这里的过滤器简单地捕获文本内容并尝试操作该内容。

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;           
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpSession session = request.getSession(false);                
        CharResponseWrapper responseWrapper = new CharResponseWrapper((HttpServletResponse) response);
        chain.doFilter(request, responseWrapper);       
                final boolean commit1 = responseWrapper.isCommitted();           
                final boolean commit2 = response.isCommitted();             
            if (!commit2) {
                final String res = responseWrapper.toString().replaceAll("(?i)</form>", "<input type=\"hidden\" name=\"superval\" value=\""+superval"\"/></form>");             
                response.getWriter().write(res);                        
            }
        return;

    }

... 这适用于大多数基本的 servlet,目标是与“replaceAll”一致。

现在,如果我创建一个带有“forward”的 servlet,代码将不起作用,它会在带有“if (!commit2)”的行处失败,因为流显然已经提交了?

例如,如果我向此 servlet 发出请求并将过滤器绑定(bind)到此 servlet,则过滤器不会完全执行。

public class TestCommitServlet extends HttpServlet {    
    private static final long serialVersionUID = 1L;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        
        req.getRequestDispatcher("TestCommitServlet2").forward(req, resp);
    }    
    @Override    
    protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

这是我要转发到的 servlet:

public class TestCommitServlet2 extends HttpServlet {    
    private static final long serialVersionUID = 1L;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        final PrintWriter out = resp.getWriter();
        resp.setContentType("text/html");
        out.println("<html><body>(v-1)testing<form action='test'><input type='submit' value='Run' /> </form></body></html>");             
    }    
    @Override    
    protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

Tl;dr :我是否必须进行此调用 'if (!commit2) {' 代码无需它即可工作。在此代码下,我将如何避免已提交的响应或 IllegalStateExceptions(与 response.getWriter().write(res); 相关的行)

有关此问题的更多信息:

https://codereview.stackexchange.com/questions/41260/capturing-content-within-a-j2ee-filter-and-then-replacing-this-text-request-for

最佳答案

我正在使用 Servlet API 3.0 来检查此场景。 我发现的是以下内容。当我调用 TestCommitServlet2 时,使用您的 servlet 和过滤器代码,我可以看到以下输出。

http://localhost:8080/Question/TestCommitServlet2

(v-1)testing
Button here
com.koitoer.CharResponseWrapper@5b5b6746

当我调用 servlet TestCommitServlet 时,我能够看到以下内容。

http://localhost:8080/Question/TestCommitServlet
(v-1)testing
Button here

这表明过滤器根本不适用于此转发的请求。

所以,我记得一些过滤器可以在不同的 DispatcherTypes 中起作用,如 FORWARD、INCLUDE、ERROR、ASYNC 和 commong REQUEST,我决定将过滤器声明更改为。

@WebFilter(filterName = "/MyFilter", urlPatterns = { "/TestCommitServlet2" }, dispatcherTypes = {
        DispatcherType.FORWARD, DispatcherType.REQUEST })
public class MyFilter implements Filter {

然后,当我通过 servlet TestCommitServlet 执行 GET 时,我得到:

(v-1)testing
 Button
com.koitoer.CharResponseWrapper@1b3bea22

上面显示过滤器现在应用于转发请求。

此外,如果我删除或注释 if (!commit2) { 代码仍然有效,因此不会出现 IllegalStateException,因为请求需要传递调用 doChain 方法的过滤器。

请注意,如果您尝试使用此替换响应的内容。

responseWrapper.toString().replaceAll

你做错了,因为responseWrapper.toString()返回类似CharResponseWrapper@5b5b6746的东西,而不是内容,如果你想修改响应,使用从HttpServletResponseWrapper扩展的包装器并覆盖正确的方法来操作输出流。

关于java - J2EE : Understanding isCommitted and Filters under this scenario,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21540010/

相关文章:

java - 如何在 Java 中验证 Date 对象

java - net.sf.jasperreports.engine.JRRuntimeException : java. io.IOException: 无法读取字体数据

java - 在 64 位机器上是否有任何理由仍然使用 int 而不是 long ?

java - 如何在jsp中拉出选定的单选按钮

java - JSP Servlet 上传图像文件

java - 使用 javascript 进行 Ajax 和 java servlet 数据传输

java - 查找 Maven 插件绑定(bind)到的默认阶段

java - 使用 lambda 在函数中传递两个参数

java - (JAVA EE)方法无法正常工作,不会引发任何错误

java - JSP 不在 linux 上创建 servlet 类