Using Pretty URLs with Spring and Annotations

I’m currently working on a Java Web App with Spring. If you aren’t familiar with the Spring Framework, especially with the annotation support, then you’ve never had the pleasure of developing a web app in Java (but you may have experienced the pain). In another post, I will explain why this is so amazing, but for now lets just assume you know.

If you notice on blogs or other sites they have something called “pretty urls”. Essentially if you had a blog, this lets you have /post/welcome-to-my-site/ instead of /post/?id=33. Using the Spring Framework and the hot new annotation support in 2.5.1, you can easily achieve that.


Specify your url on your method like so:

public static final String URL_POST = "/post/*/";

@RequestMapping(URL_POST)
public String showPost(HttpServletRequest req) {
...
}

Now all we need to do is pull out the part of the URL that has whats in the star. I’ve created the following class to assist in this manner:

public class UrlUtils {
	public static String[] breakUri(final String uri, final String expectedUrl) {
		Pattern p = Pattern.compile(expectedUrl.replace("*", "(.*?)"));
		Matcher m = p.matcher(uri);
		if (m.find()) {
			String[] ret = new String[m.groupCount()];
			for (int i=0; i<ret.length; i++) {
				ret[i] = m.group(i+1);
			}
			return ret;
		}
		else {
			return null;
		}
	}
}

So equipped with this class, you only have to do the following:

String[] parts = UrlUtils.breakUri(req.getRemoteUri(), URL_POST);
if (parts == null) {
    // Do code to show an archive or whatever you want when the * part is missing
}
else {
    // parts[0] will have what you want.
}

Note: This will also (sort of) work if you have a url like: "/post/*/*/" (the array will have a length of 2). However, if you get “/post/welcome/” as the URL from the user, breakUri() will return null, in which case you might want to check for "/post/*/".

Now, this code isn’t very complex but it does allow you to deal with pretty urls without the hassle of building the regex yourself (something you may sometimes have to do!)

Finally, I’ve put a request into the fine folks that develop the Spring Framework to include this type of functionality out of the box so your method could be something like:

@RequestMapping(POST_URL)
public String showPost(RequestParts parts) {
    if (!parts.hasParts()) {
        // show general page
    }
    else {
        // Show specific page (parts.get(0))
    }
}

Please go Vote for that feature at Spring’s issue tracking database.

  • This is actually not a bad idea. For my current projects I'm just using the URL rewrite filter. This is the easiest bet.
  • Cristian Vrabie
    I think you can achieve what you asked on Spring Jira by using AOP and intercept the request before it gets to the controller. Then use UrlUtils to break the URL into RequestParts and set them either in HttpSession or even in HttpServletRequest. I will try and see if it works, but it would be a nice solution until we have this feature built in Spring.
  • chris marx
    i believe this

    public static final String URL_POST = "/post/*/";

    should be this

    public static final String URL_POST = "/post/**/";

    with 2 asterisks. thanks for the code!!
blog comments powered by Disqus