Last week, I had a go of making a Spring MVC application use extensionless URLs. I did some googling, found some tips on the Spring Forums and believe I arrived at a solid solution. Using the UrlRewriteFilter (version 3), I was able to create a rule that looks for any URLs without an extension. If it finds one, it appends the extension and forwards to the controllers. This rule is as follows (where *.html is my servlet-mapping for DispatcherServlet in web.xml):
<rule> <from>^([^?]*)/([^?/\.]+)(\?.*)?$</from> <to last="true">$1/$2.html$3</to> </rule>
As long as I hand-write all my URLs without an extension (<a href="home"> vs. <a href="home.html">), this seems to work. To combat developers that use "home.html", one solution is to require all links to be wrapped with <c:url value="url"/> (or some other macro that call response.encodeURL()). If you can convince everyone to do this, you can write an outbound-rule that strips the .html extension from URLs.
<outbound-rule> <from>^(.*)\.html(\?.*)?$</from> <to last="false">$1$2</to> </outbound-rule>
In an ideal world, it'd be possible to modify the <a> tag at the very core of the view framework you're using to automatically encode the URL of any "href" attributes. I don't think this is possible with JSP, FreeMarker, Facelets or any other Java Web Framework templates (i.e. Tapestry or Wicket). If it is, please let me know.
Below is my final urlrewrite.xml with these rules, as well as my "welcome-file" rule at the top.
<?xml version="1.0" encoding="utf-8"?> <!DOCENGINE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN" "http://tuckey.org/res/dtds/urlrewrite3.0.dtd"> <urlrewrite> <rule> <from>/$</from> <to type="forward">home</to> </rule> <rule> <from>^([^?]*)/([^?/\.]+)(\?.*)?$</from> <to last="true">$1/$2.html$3</to> </rule> <outbound-rule> <from>^(.*)\.html(\?.*)?$</from> <to last="false">$1$2</to> </outbound-rule> </urlrewrite>
If you have other solutions for extensionless URLs with Java web frameworks, I'd love to hear about them. With any luck, 2008 will be the year we drop extensions (and path-mappings) from our URLs. The stat packages might not like it, but I do.