【问题标题】:servlet filter to rewrite URLservlet 过滤器重写 URL
【发布时间】:2013-03-16 22:03:57
【问题描述】:

我正在尝试从以下位置重写 URL:

  • localhost:8080/sendEmail/newEmail.pdf?request_id=23456&emailAddress=

收件人:

  • localhost:8080/sendEmail/newEmail.pdf?request_id=23456

过滤器类代码和映射如下。我怎样才能完成这项任务? (非常感谢您提供示例答案)。

过滤器映射:

<filter>
    <filter-name>RequestFilter</filter-name>
    <filter-class>com.abc.ms.email.filter.RequestFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>RequestFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

过滤代码:

public class RequestFilter implements Filter {
    private static final Pattern REWRITE_PATTERN = Pattern.compile("(^[1-9]\\d*)$");

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
        HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper((HttpServletRequest)req);
        String url = wrapper.getRequestURL().toString();
        String number = url.substring(url.lastIndexOf("/")).replace("/", "");
        Matcher m = REWRITE_PATTERN.matcher(number);
        if (m.find()) {
            RequestDispatcher dispatcher = wrapper.getRequestDispatcher("request?id=" + m.group(1));
            dispatcher.forward(req, res);
        } else {
            fc.doFilter(wrapper, res);
        }
    }
}

【问题讨论】:

    标签: java url-rewriting servlet-filters


    【解决方案1】:

    如果您真正需要的只是一个简单的 URL 清理,那么使用正则表达式或 URL 重写模块可能有点过头了。

    一个完全简单的实现可能是这样的:

    public class RequestFilter implements Filter {
    
        private static final String LOOK_FOR = "sendEmail/newEmail.pdf";
    
        private static final String REMOVE = "&emailAddress=";
    
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
            HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper((HttpServletRequest)req);
            String original = wrapper.getRequestURL().toString();
            if(original.contains(LOOK_FOR)) {
                String filtered = StringUtils.substringBeforeLast(original, REMOVE);
                RequestDispatcher dispatcher = wrapper.getRequestDispatcher(filtered);
                dispatcher.forward(req, res);
            } else {
                fc.doFilter(wrapper, res);
            }
        }
    }
    

    使用org.springframework.mock.web.* 类可以轻松进行单元测试:

    public class RequestFilterTest {
    
        private RequestFilter filter;
    
        @Before
        public void setUp() {
            filter = new RequestFilter();
        }
    
        @Test
        public void testRedirect() throws IOException, ServletException {
            MockHttpServletRequest request  = new MockHttpServletRequest("GET",
                    "/sendEmail/newEmail.pdf?request_id=23456&emailAddress=");
            MockHttpServletResponse response = new MockHttpServletResponse();
            MockFilterChain fc = new MockFilterChain();
    
            filter.doFilter(request , response, fc);
    
            Assert.assertEquals("http://localhost:80/sendEmail/newEmail.pdf?request_id=23456", response.getForwardedUrl());
        }
    }
    

    【讨论】:

      【解决方案2】:

      我建议使用现有的实现,而不是自己编写。

      好像有一个Java URL重写实现,就是Tuckey的URLrewriteFilter。

      见:http://tuckey.org/urlrewrite/

      这应该可以满足您的需求,而且还可以做更多。

      或者,如果您在 Web 容器前使用 apache,您可能需要查看 mod_rewrite,在 apache 上也是如此。

      http://httpd.apache.org/docs/current/mod/mod_rewrite.html

      【讨论】:

      • 我理解不情愿重新发明轮子,但我不敢相信有人会认为在 servlet 容器前添加 Apache 只是为了重写 URL 比创建一个简单的过滤器要好几行代码。
      • @stepanian 是的,这太过分了,这就是为什么我首先建议 Java 解决方案并说如果您前面已经有 apache(无论出于何种原因),mod_rewrite 可能是一种替代方法。跨度>
      猜你喜欢
      • 2011-07-25
      • 2011-04-10
      • 2023-03-14
      • 1970-01-01
      • 2013-09-02
      • 1970-01-01
      • 2012-07-11
      • 1970-01-01
      • 2014-08-21
      相关资源
      最近更新 更多