6

I have a set of JSP pages and I want to hide the .jsp extension (after a bit of research it seems it's good for SEO).

One solution I came across was the following:

<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>

And while this works, I believe I have to set up this mapping for every jsp page on my site.

I came across another solution posted here (Easy friendly URL's): Hidden features of JSP/Servlet

... which uses a simple servlet to forward the request. In my web.xml I have the following and it works fine:

<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>

Now the problem is I don't want to hit the URL: www.mydomain.com/myservlet/some-page

I want to use the URL: www.mydomain.com/some-page

So I changed the url-pattern to "/*"

<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>

But this causes an infinite loop:

    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)

Which I'm not sure how to fix. Any ideas?

Community
  • 1
  • 1
nogridbag
  • 3,521
  • 4
  • 38
  • 51

2 Answers2

6

A servlet which is mapped on /* will also run on RequestDispatcher#forward() calls. So if you're performing a forward in that servlet, it would call itself everytime in an infinite loop. That explains the StackOverflowError.

After all, you should not be using /* for servlets at all. It only makes sense on servlet filters. Put the servlet mapping back on a more specific URL pattern and create a filter on /* which forwards to the desired servlet when necessary. You of course don't want to have the servlet to handle for example images/CSS/JS files. Assuming that they're all placed in /resources folder and that your front controller is mapped on /myservlet/*, then do the following job in 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);
}

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Silly question. Do I even need the servlet in the first place? Can the filter forward directly to the jsp pages? – nogridbag May 01 '12 at 18:50
  • 2
    If the sole functional requirement is "pretty URLs" and not "front controller", then you can use alone a filter, yes. There are even 3rd party libraries for this such as [Tuckey's URLRewriteFilter](http://code.google.com/p/urlrewritefilter/) and [Rewrite](http://ocpsoft.org/rewrite/) which are similar to Apache HTTPD's `mod_rewrite`. But if you actually need a front controller (which will also handle HTTP request preprocessing and postporocessing), better keep it in the servlet. – BalusC May 01 '12 at 18:55
1

You should use UrlRewriteFilter

You could use some like this on your configuration file(urlrewrite.xml):

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

UrlRewriteFilter is on the a comment, but I consider it should be an independent answer.

Steven Lizarazo
  • 5,320
  • 2
  • 28
  • 25