servlet过滤器中包含的HttpServletResponse不执行重定向

时间:2014-07-26 08:33:11

标签: spring servlets spring-security servlet-filters

我在servlet应用程序中使用Spring 4.0.6。我有一个抽象的基本控制器,其中包含一些通用方法供我的所有控制器使用。

其中一种方法是重定向。我想要一个带签名的方法

redirect(String path)

要发送重定向,我正在使用

response.sendRedirect(response.encodeRedirectURL(path));

由于我想保持方法签名简洁明了,我需要访问超类方法中的响应对象。

为了做到这一点,我遵循了在线发现的建议,并使用ThreadLocal HttpServletResponse定义了一个servlet过滤器。

public class ResponseFilter extends OncePerRequestFilter {

    private static final ThreadLocal<HttpServletResponse> responses = new ThreadLocal<HttpServletResponse>();

    public static HttpServletResponse getResponse() {
        return responses.get();
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            responses.set(response);
        } finally {
            try {
                filterChain.doFilter(request, response);
            } finally {
                responses.remove();
            }
        }
    }
}

当我使用带有Java配置的Spring安全性时,我在我的WebSecurityConfigurerAdapter子类中添加了这个过滤器:

.addFilterAfter(rf, SwitchUserFilter.class)

请注意,我还尝试在过滤链中首先添加过滤器,并尝试使用Interceptor。都具有相同的结果。

我已经在响应对象上比较了哈希码,而且我可以说,哈希码匹配,但重定向似乎被忽略了。我还在Eclipse中查看了断点上的对象id,再次,我有一个匹配。症状是spring DispatcherServlet进入processDispatchResult并且似乎认为它需要解析视图。该视图不存在,因为我希望进行重定向:

javax.servlet.ServletException: File &quot;/WEB-INF/views/application/redirecttest.jsp&quot; not found

我注意到,如果我在请求映射控制器方法签名中添加响应对象,则超类重定向似乎有效(即使我根本不使用控制器方法响应对象)。

不幸的是,这种行为在Mac和Linux上都是可重现的。我使用Tomcat 7作为容器。

1 个答案:

答案 0 :(得分:1)

您的过滤器应该可以正常工作,您面临的问题是另一个问题。如果您正在使用视图(如示例中所示),则需要从控制器返回重定向视图以强制重定向;只是指示响应对象重定向将无法工作,因为Spring MVC基础结构将在响应返回到Servlet容器之前尝试执行其操作(即视图解析)。

例如,如果使用约定从控制器方法将视图名称作为String返回,则需要在控制器中执行以下操作:

@RequestMapping("/redirectTest")
public String redirectTest() {
  return "redirect:http://www.example.com";
}