Java 实现一个URL过滤器

Java 实现一个URL过滤器,java,tomcat,servlets,embedded-tomcat-7,tomcat8,Java,Tomcat,Servlets,Embedded Tomcat 7,Tomcat8,带有Servlet和过滤器的嵌入式Tomcat的简单实例: Tomcat tomcat = new Tomcat(); Context rootCtx = tomcat.addContext("", base.getAbsolutePath()); FilterDef filterDefinition = new FilterDef(); filterDefinition.setFilterName(

带有Servlet和过滤器的嵌入式Tomcat的简单实例:

            Tomcat tomcat = new Tomcat();
            Context rootCtx = tomcat.addContext("", base.getAbsolutePath());
            FilterDef filterDefinition = new FilterDef();
            filterDefinition.setFilterName(URLFilter.class.getSimpleName());
            filterDefinition.setFilterClass(URLFilter.class.getName());
            rootCtx.addFilterDef(filterDefinition);

            FilterMap filter1mapping = new FilterMap();
            filter1mapping.setFilterName(URLFilter.class.getSimpleName());
            filter1mapping.addURLPattern("/*");
            rootCtx.addFilterMap(filter1mapping);

            Tomcat.addServlet(rootCtx, "Servlet1", new Servlet1());
            rootCtx.addServletMapping("/Servlet1", "Servlet1");
URL过滤器实现:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
    Boolean filtered = false;
    System.out.println("request intercepted");
    if (request.getAttribute("filtered") != null) {
        filtered = true;
        request.setAttribute("filtered", filtered);
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.sendRedirect("/Servlet1");
        return;
    } else {
        filterChain.doFilter(request, response);
    }
}
出于某种原因,这会在无限循环中结束,并且永远不会到达Servlet1。实现URL过滤器的正确方法是什么,这样我就可以在发送响应之前仔细检查请求周围的参数了?

查看JavaDocs以了解更多信息。您在每个请求上都告诉客户机返回到/Servlet1,但随后您将无限期地对其进行过滤。在某个时候,您需要停止在过滤器中发送重定向

进一步澄清。如果您不打算主动筛选请求,那么您只需要调用

filterChain.dofilter(request, response);
不要发回重定向,除非你真的想发送HTTP 302(临时重定向)。Servlet筛选器链是Servlet流程的重要组成部分,尽管看起来有点违反直觉,但您可以通过调用filterChain.doFilter命令使筛选器看起来什么都不做,该命令允许请求继续处理由应用程序服务器配置的其他筛选器


我不清楚的是过滤你的过滤器试图做什么。如果您打算按URL进行筛选,则应查找匹配的URL,然后仅在存在匹配的URL时重定向。

因为这解决了您的问题,所以将其作为答案发布

首先,您需要确保沿着应用程序筛选器链传递请求,或者重定向请求:

@Override
public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain filterChain) throws IOException, ServletException {

    Boolean filtered = false;
    System.out.println("request intercepted");
    if (!filtered) {
        filtered = true;
        ((HttpServletResponse) response).sendRedirect("/Servlet1");
        return;
    }

    filterChain.doFilter(request, response);
}
然后,您需要确保过滤器知道传入请求何时已被重定向,以便不再重定向:

@Override
public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain filterChain) throws IOException, ServletException {

    Boolean filtered = false;
    System.out.println("request intercepted");
    if (request.getAttribute("filtered") != null) {
        filtered = (Boolean) request.getAttribute("filtered");
    }

    if (!filtered) {
        request.setAttribute("filtered", Boolean.TRUE);
        ((HttpServletResponse) response).sendRedirect("/Servlet1");
        return;
    }

    filterChain.doFilter(request, response);
}

看起来您缺少对
chain.doFilter(请求、响应)
的调用。如果您在
doFilter
方法的末尾包含它,行为是否会改变?抱歉,我最初的评论太仓促,不够具体。只有在不发送重定向时,才需要调用
doFilter
。当你重定向时,你应该返回
之后,
doFilter
用于不重定向时。如果要执行大量重定向,请查看。它就是为了这个目的而做的。也许可以试着从这个角度来看它:你的过滤器如何知道它之前是否已经重定向了一个请求?目前它没有-它假设它接收到的任何东西还没有被重定向,并重定向它。您可以向请求添加一个属性,例如
request.setAttribute(“redirected”,“true”)
,然后让筛选器检查该属性以查看它是否已重定向。如果没有,请修改属性然后重定向它,否则不要重定向它并沿着应用程序筛选器链传递请求。这是,但我认为如果(request.getRequestURI.equals(“/Servlet1”){filterChain.dofilter(request,response);}