Java过滤器URL重写循环问题

Posted

技术标签:

【中文标题】Java过滤器URL重写循环问题【英文标题】:Java Filter URL Rewriting Loop Problem 【发布时间】:2011-05-28 00:31:06 【问题描述】:

我希望有人能指出我在这里出错的地方。我正在尝试创建一个类似于Paul Tuckey's URLRewriteFilter 的简单过滤器,但精简后只做我需要它做的事情。

我无法让它停止循环返回原始 URI。我已经窥探了 URLRewriteFilter 代码,它似乎在做我正在做的基本相同的事情。这是我的过滤器代码:

public static final String dispatcherURI = "/Dispatcher?q=";
public void doFilter(final ServletRequest request, final ServletResponse response,
                     final FilterChain chain)
        throws IOException, ServletException 
    final HttpServletRequest rq = (HttpServletRequest)request;
    final HttpServletResponseWrapper rsw =
        new HttpServletResponseWrapper((HttpServletResponse)response);
    final String uri = rq.getRequestURI();
    if (uriIsDispatchable(uri)) 
        final String forwardPath = dispatcherURI+uri;
        rq.getRequestDispatcher(forwardPath).forward(rq, rsw);
        LOG.info("Forward From: "+uri+", To: "+forwardPath);
    
    else 
        try  chain.doFilter(request, response); 
        catch (Exception e) 
            LOG.error(e);
            throw new RuntimeException(e);
        
    


// checks URI against an ArrayList of URIs that should be ignored.
private static boolean uriIsDispatchable (final String uri) 
    boolean result = true;
    for (String i : ApplicationValues.uriIgnore) 
        if (uri.indexOf(i) == 0) 
            result = false;
            break;
        
    
    return result;

这是 web.xml 中的过滤器条目

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>myapp.filter.URLRewrite</filter-class>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

关于代码的一些注释: 像 /home 这样的 URI 应该像这样转发到调度程序 servlet:/Dispatcher?q=/home 然后调度 servlet 根据查询字符串中的内容确定要执行的代码。

过滤器正确地忽略了“uriIgnore”ArrayList(包括/Dispatcher)中的URI,但转发继续在/home上循环。为了完整起见,这里是在上面的 uriIsDispatchable 方法中搜索到的 uriIgnore ArrayList 的内容:

public static final List<String> uriIgnore = new ArrayList<String>(4);
static 
  uriIgnore.add("/Dispatcher");
  uriIgnore.add("/netbeans-tomcat-status-test");
  uriIgnore.add("/resources");
  uriIgnore.add("/robots.txt");

另外,我在 Apache 后面运行最新的 Tomcat 6。

感谢任何帮助。谢谢。

【问题讨论】:

【参考方案1】:

我想当程序执行语句时:rq.getRequestDispatcher(forwardPath).forward(rq, rsw); 它会调用doFilter() method again, and then the program will be an endless loop. I think you can add a parameter to tell the url is from another doFilter(),所以它可以识别然后转发或不转发。

【讨论】:

转发会导致doFilter再次运行,但我认为问题在于转发的请求保留了原始URI而不是转发的URI,从而导致循环。从我可以从 URLRewriteFilter 代码中收集到的内容来看,他使用了与我正在使用的相同的转发调用,但他没有循环。我已经在我的服务器上使用相同的规则尝试了 Tuckey URLRewiriteFilter,它工作得很好。我敢肯定,我缺少一些简单而明显的东西。【参考方案2】:

当我有时间进一步阅读 URLRewrite 过滤器代码时,我会设法解决这个问题,但与此同时,如果我真的想要最高性能的 URL 重写,我会让 mod_rewrite 和 Apache 做它。

我的解决方案(我相信也有更好的方法):

# .htaccess file contents
# Apache has the same docroot as the Java web app.
# Java webapp is running on port 8084
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %REQUEST_FILENAME !-f [NC,OR]
RewriteCond %REQUEST_FILENAME !-d
# directory where images, static html files and JS scripts are located.
# Apache will serve these.
RewriteRule ^resources - [L,NC]
# obviously, we want Apache to serve robots.txt
RewriteRule ^robots.txt$ - [L,NC]
RewriteRule ^(.*)$ http://localhost:8084/Dispatcher?q=$1 [L,P,QSA]
</IfModule>

【讨论】:

当我找到解决这个问题的 Java 解决方案时,我一定会在这里发布。【参考方案3】:

同样的无限循环问题here,配置urlrewriter只过滤REQUEST,不过滤FORWARD,试试看 在你的 web.xml 中像这样:

 <filter-mapping>
     <filter-name>UrlRewriteFilter</filter-name>
     <url-pattern>/*</url-pattern>
     <dispatcher>REQUEST</dispatcher>
 </filter-mapping>

在这种情况下,规则处理在转发后不会再次执行。

【讨论】:

以上是关于Java过滤器URL重写循环问题的主要内容,如果未能解决你的问题,请参考以下文章

servlet 过滤器重写 URL

qt源码解析1--事件循环原理(重写事件函数,事件过滤器等)

Java过滤器无限循环[重复]

特定于请求参数的 Java 过滤器 URL 模式

在 Java 过滤器中获取配置的 url 模式 [重复]

UrlRewriteFilter 运行元素产生 404 但元素在 GAE/Java 上工作正常