在 servlet 重定向之前使用过滤器修改响应 URL (Java/Tomcat)

Posted

技术标签:

【中文标题】在 servlet 重定向之前使用过滤器修改响应 URL (Java/Tomcat)【英文标题】:Modify response URL with filter before servlet redirects (Java/Tomcat) 【发布时间】:2017-01-02 08:43:51 【问题描述】:

我正在尝试使用servlet filter 修改servlet 的响应URL, servlet 本身发出@​​987654331@ 之前。但我对此无能为力。我首先使用 servlet 进行了测试,然后设置了一些虚拟的 JSP 页面来复制 servlet 的相同基本行为。 servlet 来自第三方供应商,无法修改。

对于这个问题,我会坚持使用 JSP 页面,并假装它们无法修改。如果我可以修改 servlet,就不需要发布这个问题了。

我还参考了以下两个主题来帮助我构建过滤器。

Redirecting a request using servlets and the "setHeader" method not working

Looking for an example for inserting content into the response using a servlet filter

servlet/JSP 中发生的情况是它使用https 加载,然后它基于当前 URL 构建一个新的 URL,使用 http,附加一个 querystring parameter,cacheid,并重新加载页面,即

    https://example.com/test/testfilter.jsp http://example.com/test/testfilter.jsp?cacheid=123456

我希望它看起来像这样:

    https://example.com/test/testfilter.jsp https://example.com/test/testfilter.jsp?cacheid=123456

所以我的想法是构建一个拦截响应的过滤器, servlet/JSP 发出response.sendRedirect,修改位置和状态标头,它应该可以工作。但这并不完全奏效。

testfilter.jsp

<%

if (request.getParameter("cacheid") == null) 
    response.sendRedirect("http:/example.com/test/testfilter.jsp?cacheid=123456");


%>
<html>
<head></head>
<body>Test</body>
</html>

过滤器

这是我的doFilter 方法:

public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException 
    // TODO Auto-generated method stub
    System.out.println("BEFORE filter");

    PrintWriter out = response.getWriter();

    CharResponseWrapper responseWrapper = new CharResponseWrapper((HttpServletResponse) response);

    if ( ((HttpServletRequest)request).getParameter("cacheid") == null ) 
        // Not sure how to append querystring parameter
        responseWrapper.setHeader("location", "https://example.com/test/testfilter.jsp?cacheid=123456");
        responseWrapper.setStatus(HttpServletResponse.SC_FOUND);
           

    chain.doFilter(request, responseWrapper);

    String servletResponse = new String(responseWrapper.toString());

    out.write(servletResponse + " filtered"); // Here you can change the response

    System.out.println("AFTER filter, original response: " + servletResponse);

    if ( ((HttpServletRequest)request).getParameter("cacheid") == null ) 
        // Not sure how to append querystring parameter
        responseWrapper.setHeader("location", "https://example.com/test/testfilter.jsp?cacheid=123456");
        responseWrapper.setStatus(HttpServletResponse.SC_FOUND);
      

小问题是我不确定如何在这个修改后的响应中附加查询字符串参数、cacheid 及其值。

主要问题是过滤器似乎只在第二次调用 testfilter.jsp 时触发(使用查询字符串参数 cacheid)。这是原始响应:

https://example.com/test/testfilter.jsp

HTTP/1.1 302 Moved Temporarily
Content-Length: 0
Content-Type: text/html;charset=ISO-8859-1
Location: http://example.com/test/testfilter.jsp?cacheid=123456
Server: Microsoft-IIS/7.5
Set-Cookie: JSESSIONID=66ACCD1EFF485CE820BB9E705311C31D; Path=/test; Secure
Date: Thu, 25 Aug 2016 19:18:54 GMT

http://example.com/test/testfilter.jsp?cacheid=123456

HTTP/1.1 200 OK
Content-Length: 60
Content-Type: text/html;charset=ISO-8859-1
Server: Microsoft-IIS/7.5
Set-Cookie: JSESSIONID=1342FB2D65F5568AC7EA1EF21E6FB8E4; Path=/test
Date: Thu, 25 Aug 2016 19:18:54 GMT

<html>
<head></head>
<body>Test</body>
</html> filtered

如果我可以让过滤器在它发送自己的重定向之前第一次拦截它,我就会被设置。但事情似乎从来没有那么简单。

我希望我解释得足够好,问题是什么。任何帮助将不胜感激。

谢谢。

【问题讨论】:

我遇到了同样的问题。您是否找到了解决此问题的方法或变通方法? 【参考方案1】:

设置 nginx 并将此类逻辑移动到 Nginx 指令 proxy_redirect 是一种解决方法。

【讨论】:

以上是关于在 servlet 重定向之前使用过滤器修改响应 URL (Java/Tomcat)的主要内容,如果未能解决你的问题,请参考以下文章

在 servlet 过滤器中使用请求参数将 JSF ajax 请求重定向到 URL

我应该使用 servlet 还是过滤器来重定向 URL?

Servlet过滤器登录重定向无限循环[重复]

Servlet过滤器重定向:如何在chain.doFilter(request,resp)之后重定向;

使用 java servlet 在重定向响应中丢失 HTTP 自定义标头

如何在从 servlet 过滤器执行 HTTP 重定向时保留请求正文