【问题标题】:GWT Filter never executedGWT 过滤器从未执行
【发布时间】:2013-04-11 09:17:48
【问题描述】:

我正在开发一个 GWT 过滤器以使我的 GWT 应用程序可抓取。这个想法是,当它发现这样一个丑陋的 URL 时:

http://www.myapp.com/?_escaped_fragment_=v;id=Mv67mC13Yizr

介绍好的:

http://www.myapp.com/#!v;id=Mv67mC13Yizr

但是,代码永远不会到达 doFilter()。为什么?

Web.xml

<filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

DispatchServletModule.java

public class DispatchServletModule extends ServletModule {

    @Override
    public void configureServlets() {
        serve("/" + ActionImpl.DEFAULT_SERVICE_NAME)
                .with(DispatchServiceImpl.class);
        filter("/").through(CrawlerServiceImpl.class);
    }
}

CrawlerServiceImpl.java

    @Singleton
    public final class CrawlerServiceImpl implements Filter {
      private static final String ESCAPED_FRAGMENT_FORMAT1 = "_escaped_fragment_=";
      private  final int ESCAPED_FRAGMENT_LENGTH1 = ESCAPED_FRAGMENT_FORMAT1.length();
      private static final String ESCAPED_FRAGMENT_FORMAT2 = "&"+ESCAPED_FRAGMENT_FORMAT1;
      private  final int ESCAPED_FRAGMENT_LENGTH2 = ESCAPED_FRAGMENT_FORMAT2.length();

      @Inject(optional = true)
      private final Provider<WebClient> webClientProvider = null;

      @Override
      public void init(FilterConfig filterConfig) throws ServletException {  
      }
      @Override
      public void destroy() {
      }

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

        final String requestURI = req.getRequestURI();
        if ((queryString != null) && (queryString.contains(ESCAPED_FRAGMENT_FORMAT1))) {
          try {
            StringBuilder pageNameSb = new StringBuilder("http://");
            pageNameSb.append(req.getServerName());
            if (req.getServerPort() != 0) {
              pageNameSb.append(":");
              pageNameSb.append(req.getServerPort());
            }
            pageNameSb.append(requestURI);
            queryString = rewriteQueryString(queryString);
            pageNameSb.append(queryString);
            String pageName = pageNameSb.toString();
            WebClient webClient;
            if( webClientProvider == null )
              webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
            else
              webClient = webClientProvider.get();

            webClient.setThrowExceptionOnScriptError(false);
            webClient.setJavaScriptEnabled(true);
            HtmlPage page = webClient.getPage( pageName );

            res.setContentType("text/html;charset=UTF-8");
            PrintWriter out = res.getWriter();
            out.println("<hr />");
            out.println("<center><h3>You are viewing a non-interactive page that is intended for the crawler.  "
                + "You probably want to see this page: <a href=\""
                + pageName
                + "\">"
                + pageName + "</a></h3></center>");
            out.println("<hr />");     
            out.println(page.asXml());
            webClient.closeAllWindows();
            out.println("");
            out.close();
          }
          catch( Exception e ) {
          }
        } else {
          chain.doFilter(request, response);
        }
      }

      private String rewriteQueryString(String queryString) throws UnsupportedEncodingException {
        int index = queryString.indexOf(ESCAPED_FRAGMENT_FORMAT2);
        int length = ESCAPED_FRAGMENT_LENGTH2;
        if (index == -1) {
          index = queryString.indexOf(ESCAPED_FRAGMENT_FORMAT1);
          length = ESCAPED_FRAGMENT_LENGTH1;
        }
        if (index != -1) {
          StringBuilder queryStringSb = new StringBuilder();
          if (index > 0) {
            queryStringSb.append("?");
            queryStringSb.append(queryString.substring(0, index));
          }
          queryStringSb.append("#!");
          queryStringSb.append(URLDecoder.decode(queryString.substring(index
              + length, queryString.length()), "UTF-8"));
          return queryStringSb.toString();
        }
        return queryString;
      }
}

【问题讨论】:

    标签: java gwt servlets web-crawler servlet-filters


    【解决方案1】:

    您的&lt;url-pattern&gt; 无效,* 只能作为模式的/* 后缀或*. 前缀;并且模式仅适用于路径,而不适用于查询字符串。

    您必须将您的过滤器映射到/ 并在过滤器中检查_escaped_fragment_ 参数(我会亲自检查getMethod() 是否为"GET",然后使用getParameter("_escaped_fragment_"))来决定是否使用你的WebClient 在服务器端获取和呈现页面,或者只是链接到下一个过滤器。

    请注意,当您在 web.xml 中声明过滤器时,Guice 不会注入它,所以就像 Dvd Prd 所说的那样,您可能宁愿在 Guice 的 ServletModule 中声明过滤器。请注意,与 standard 映射类似,只有路径匹配,因此上述方法仍然适用(甚至 filterRegex() 也不起作用)。

    【讨论】:

    • 谢谢。然后,按照您在上一段中所说的,从上面的代码中,我刚刚从 web.xml 中删除了这个过滤器条目,并在我的 DispatchServletModule.java 中插入了 Dvd Prd 建议的代码。但还是不行。请在上方找到新代码。
    • 正如我所说,模式仅在路径上匹配,因此即使在 Guice ServletModule 中绑定,您也必须绑定到 / 并修改您的过滤器以处理查询字符串(首先我的部分回复)
    • 谢谢。我再次更新了它: filter("/").through(CrawlerServiceImpl.class);但是,doFilter() 中的代码永远不会执行。有什么想法吗?
    • 如果您的/ 是静态页面并且您从AppEngine 提供您的应用程序,那么this is expected;否则我不知道。您是否在GuiceFilter 中设置了断点以查看它是否被调用以及使用哪个 URL?
    【解决方案2】:

    Guice 采用所有过滤器。要添加过滤器,您需要在 guice servlet module 中声明它:

    filter("/?_escaped_fragment_=*").through(CrawlerServiceImpl.class);

    【讨论】:

    • GuiceFilterCrawlerServletFilter 之后声明和映射,以便在GuiceFilter 之前执行。
    猜你喜欢
    • 2014-12-12
    • 2013-01-05
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多