Spring-Boot:用于重定向的 Web 过滤器

chr*_*s01 5 java servlet-filters spring-boot

我有一个过滤器。如果请求 /a,它应该重定向到 /b。

public class WebFilter extends GenericFilterBean
{ 
 @Override
 public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
 {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    String path = req.getRequestURI ().toString ();

    if (path.equals ("/a") == true)
    {
        System.out.println ("FILTER: a -> b");
        res.reset ();
        res.resetBuffer();
        res.sendRedirect ("b");
    }

    chain.doFilter (req, res);
  }
}
Run Code Online (Sandbox Code Playgroud)

这是内容的处理程序。

@Component
@Controller
@RequestMapping ("/")
public class WebHandler
{

 @RequestMapping ("/a")
 public String a ()
 {
    System.out.println ("a");
    return "a"; // point to a.jsp
 }

 @RequestMapping ("/b")
 public String b (HttpSession ses)
 {
     System.out.println ("b");
     return "b"; // point to b.jsp
 }
}
Run Code Online (Sandbox Code Playgroud)

如果我在浏览器中请求 /a,那么这就是输出。

FILTER: a -> b
IN a
IN b
Run Code Online (Sandbox Code Playgroud)

为什么要调用方法a?我只期望 b,因为我在 doFilter 中从 a 重定向到 b。我怎样才能做到这一点?

123*_*123 9

因此,您实际上正在执行重定向,尽管您似乎只是想将请求定向到不同的控制器映射。

    res.sendRedirect ("b");
Run Code Online (Sandbox Code Playgroud)

只需将响应代码更改为302并添加一个location字段,您仍然会点击第一个控制器,这就是您仍然a在日志中看到的原因。然后,浏览器确认此重定向指令并将发送第二个/b.

实现您想要的效果的一种方法是从提交的请求创建一个新的请求,然后简单地重写该getRequestUri()方法。

    @Override
    public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        String path = req.getRequestURI();


        if (path.equals("/a")) {
            req = new HttpServletRequestWrapper((HttpServletRequest) request) {
                @Override
                public String getRequestURI() {
                    return "/b";
                }
            };
        }

        chain.doFilter (req, res);
    }
Run Code Online (Sandbox Code Playgroud)

然后将其传递到过滤器链,一切都会继续,就像原始请求一样