Servlet过滤器用于重写URL

3
我正在尝试重写一个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);
        }
    }
}
2个回答

7
如果你只是需要一个简单的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());
    }
}

3

1
我理解不愿重复造轮子的心态,但我无法相信有人会认为在一个Servlet容器前添加Apache来重写URL比编写几行代码创建一个简单的过滤器更好。 - stepanian
@stepanian 是的,那会过度杀伤力,这就是为什么我首先建议使用Java解决方案,并说如果您已经在前面使用了Apache(出于任何原因),mod_rewrite可能是另一种替代方法。 - marc82ch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接