StackOverflowError в сопоставлении сервлетов с url-шаблоном "/*"


У меня есть набор страниц JSP, и я хочу скрыть их .расширение jsp (после небольшого исследования кажется, что это хорошо для SEO).

Одно решение, с которым я столкнулся, было следующим:

<servlet>
    <servlet-name>mypage</servlet-name>
    <jsp-file>/some-page.jsp</jsp-file>
</servlet>
<servlet-mapping>
    <servlet-name>mypage</servlet-name>
    <url-pattern>/some-page</url-pattern>
</servlet-mapping>

И хотя это работает, я считаю, что должен настроить это сопоставление для каждой страницы jsp на моем сайте.

Я наткнулся на другое решение, опубликованное здесь (простой дружественный URL): скрытые возможности JSP / Servlet

... который использует простой сервлет для пересылки запроса. В моей паутине.в XML я имейте следующее, И это прекрасно работает:

<servlet>
    <servlet-name>MyServletName</servlet-name>
    <servlet-class>myservlets.PrettyUrlServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyServletName</servlet-name>
    <url-pattern>/myservlet/*</url-pattern>
</servlet-mapping>

Теперь проблема в том, что я не хочу попасть на URL: www.mydomain.com/myservlet/some-page

Я хочу использовать URL: www.mydomain.com/some-page

Поэтому я изменил url-шаблон на "/* "

<servlet>
    <servlet-name>MyServletName</servlet-name>
    <servlet-class>myservlets.PrettyUrlServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyServletName</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

Но это приводит к бесконечному циклу:

    Exception in thread "http-bio-8080-exec-1" java.lang.StackOverflowError
            at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:219)
            at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:228)
            .
            .
            at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:228)
            at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:228)
            at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
            at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
            at myservlets.PrettyUrlServlet.doGet(PrettyUrlServlet.java:22)

Который я не знаю, как исправить. Есть идеи?

2 4

2 ответа:

Сервлет, отображенный на /*, также будет работать на вызовах RequestDispatcher#forward(). Поэтому, если вы выполняете форвард в этом сервлете, он будет вызывать себя каждый раз в бесконечном цикле. Это объясняет StackOverflowError.

В конце концов, вы вообще не должны использовать /* для сервлетов. Это имеет смысл только на фильтрах сервлетов. Поместите отображение сервлета обратно на более конкретный шаблон URL и создайте фильтр на /*, который при необходимости перенаправляет к нужному сервлету. Вы, конечно, не хотите иметь сервлет для обработки, например, файлов images / CSS/JS. Предположим, что все они помещены в папку /resources и что ваш фронт-контроллер отображен на /myservlet/*, затем выполните следующую работу в doFilter():

HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());

if (path.startsWith("/resources/")) {
    // Just let container's default servlet do its job.
    chain.doFilter(request, response);
}
else {
    // Delegate to your front controller.
    request.getRequestDispatcher("/myservlet" + path).forward(request, response);
}

См. также:

Вы должны использовать UrlRewriteFilter

Вы можете использовать некоторые из них в вашем файле конфигурации (urlrewrite.xml):

<rule>
    <from>/products/([a-zA-Z0-9._%]+)</from>
    <to>/products.jsp?id=$1</to>
</rule>

UrlRewriteFilter находится в комментарии a, но я считаю, что это должен быть независимый ответ.