Как использовать фильтр сервлета в Java для изменения URL-адреса входящего запроса сервлета?

186

Как я могу использовать фильтр сервлета для изменения URL-адреса входящего запроса сервлета

http://nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123

в

http://nm-java.appspot.com/Check_License?Contact_Id=My_Obj_123

?


Обновление : в соответствии с шагами BalusC ниже, я придумал следующий код:

public class UrlRewriteFilter implements Filter {

    @Override
    public void init(FilterConfig config) throws ServletException {
        //
    }

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

        if (requestURI.startsWith("/Check_License/Dir_My_App/")) {
            String toReplace = requestURI.substring(requestURI.indexOf("/Dir_My_App"), requestURI.lastIndexOf("/") + 1);
            String newURI = requestURI.replace(toReplace, "?Contact_Id=");
            req.getRequestDispatcher(newURI).forward(req, res);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void destroy() {
        //
    }
}

Соответствующая запись web.xmlвыглядит следующим образом:

<filter>
    <filter-name>urlRewriteFilter</filter-name>
    <filter-class>com.example.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>urlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Я пробовал перенаправление на стороне сервера и на стороне клиента с ожидаемыми результатами. Это сработало, спасибо BalusC!

Фрэнк
источник
Похожий вопрос: stackoverflow.com/questions/2723829/…
BalusC
Какую версию спецификации сервлета вы используете? То, как вы пересылаете запросы, меняется в разных версиях.
Romain Hippeau
Смотрите этот пост, он также имеет фильтр, который делает то, что вы хотите
Romain Hippeau
Обратите внимание, что если ваш исходный URL-адрес содержит параметры, т.е. nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123 ? ** param1 = A & param2 = B **, то эти параметры также будут перенаправлены на следующий сервлет / jsp. Я не нашел способа избавиться или заменить оригинальные параметры (только с помощью HttpServletRequestWrapper). Есть идеи? .. Обновление: кажется, что http://ocpsoft.org/opensource/how-to-safely-add-modify-servlet-request-parameter-values/ решает эту проблему.
Лопотун
Спасибо, я искал пример переписывания и шифрования URL.
Адитья Яда

Ответы:

281
  1. Реализовать javax.servlet.Filter.
  2. В doFilter()методе приведите входящее ServletRequestк HttpServletRequest.
  3. Используйте, HttpServletRequest#getRequestURI()чтобы схватить путь.
  4. Используйте простые java.lang.Stringметоды , такие как substring(), split(), concat()и так далее , чтобы извлечь часть интереса и составить новый путь.
  5. Используйте либо , ServletRequest#getRequestDispatcher()а затем RequestDispatcher#forward()направить запрос / ответ на новый URL - адрес ( на стороне сервера переадресации, не отраженные в адресной строке браузера), или бросить входящий ServletResponseв HttpServletResponseи затем HttpServletResponse#sendRedirect()перенаправить ответ на новый URL - адрес ( на стороне клиента перенаправления, отраженные в адресная строка браузера).
  6. Зарегистрируйте фильтр web.xmlна условиях url-patternиз /*или /Check_License/*, в зависимости от контекста пути, или если вы на Servlet 3.0 уже, использовать @WebFilterаннотацию , что вместо этого.

Не забудьте добавить проверку в коде, если URL-адрес необходимо изменить, а если нет , то просто позвоните FilterChain#doFilter(), иначе он будет вызывать себя в бесконечном цикле.

В качестве альтернативы вы также можете просто использовать существующий сторонний API, чтобы выполнить всю работу за вас, например , UrlRewriteFilter Tuckey, который можно настроить так же, как и в Apache mod_rewrite.

BalusC
источник
1
Любой пример кода doFilter () где-то, что делает выше? Спасибо.
Фрэнк
20
На каком именно этапе вы застряли? Мой ответ почти пишет сам код. Вы также заметили, что синие ссылки на код на самом деле являются ссылками на Javadocs, который подробно описывает поведение класса / метода? В любом случае, вы можете найти здесь и здесь хорошие учебники JSP / Servlet, в частности , это один о фильтрах.
BalusC
1
Я полагаю, что это правильно, но если фильтр является одним из первых в цепочке и RequestDispatcher#forward()выполняется, остальные фильтры не будут выполнены. Итак, не будет ли лучший способ сделать это как сервлет?
lucasvc
2
@datakey: просто измените порядок следования или добавьте <dispatcher>FORWARD</dispatcher>в отображение фильтра.
BalusC
1
@ JimJim2000: просто измените порядок следования или добавьте <dispatcher>FORWARD</dispatcher>в отображение фильтра.
BalusC
21

Вы можете использовать готовый фильтр Url Rewrite с таким правилом:

<rule>
  <from>^/Check_License/Dir_My_App/Dir_ABC/My_Obj_([0-9]+)$</from>
  <to>/Check_License?Contact_Id=My_Obj_$1</to>
</rule>

Проверьте примеры для более ... примеров.

Паскаль Тивент
источник
7

Простой фильтр JSF Url Prettyfier, основанный на ответах BalusC . Фильтр перенаправляет все запросы, начиная с пути / ui (предположим, что у вас есть все ваши файлы xhtml, хранящиеся там), по тому же пути, но с добавлением суффикса xhtml.

public class UrlPrettyfierFilter implements Filter {

    private static final String JSF_VIEW_ROOT_PATH = "/ui";

    private static final String JSF_VIEW_SUFFIX = ".xhtml";

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = ((HttpServletRequest) request);
        String requestURI = httpServletRequest.getRequestURI();
        //Only process the paths starting with /ui, so as other requests get unprocessed. 
        //You can register the filter itself for /ui/* only, too
        if (requestURI.startsWith(JSF_VIEW_ROOT_PATH) 
                && !requestURI.contains(JSF_VIEW_SUFFIX)) {
            request.getRequestDispatcher(requestURI.concat(JSF_VIEW_SUFFIX))
                .forward(request,response);
        } else {
            chain.doFilter(httpServletRequest, response);
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }

}
Экстремальный байкер
источник