Hello URL Rewriting! March 1, 2008
After about an hour of programming, I have my URLs in a search engine friendly format! This has many other benefits as well:
For instance, I don't have to know the ID of the news I want to link to, just the title. So, I can make a link to a news item I have previously written by typing in the title in a format that it expects. For the news item titled "The Guitar Player", the link will be "the-guitar-player". Click here to test.
Also, if I want, I can modify my "text writer" component in JSF, to search for strings like "[[The Guitar Player]]", and to write out the url, namely "/news/the-guitar-player". Or I'd have to make it "[[News|The Guitar Player]]" if I want to add more dynamic linking, say for photos, downloads, comments, etc. This is much like a Wiki works. It can be a "news wiki" or a "wiki blog" or something ridiculous like that.
Also, after I save this, it will probably write out all of the news in my atom.xml file... it might take a while, there'll be 454 news items! That's ok though. I'll probably have to delegate that task to a new thread, so I can get to adding more news right away.
Categories are changed for rewriting purposes. "Labels" have not been updated yet. I have to make a new page because a "Label" object can pertain to Downloads and Pictures, so I have to list results for each, or modify the URL rewrite filter to accept "/picture/label/me" and "/download/label/music" to list pictures of me and my music downloads, respectively.
I don't run Apache HTTPD, so I had to write the URL rewriter all in Java for Tomcat. It wasn't too bad. Regular Expressions are neat.
The meat:String url = ((HttpServletRequest)req).getRequestURL().toString().replace(HttpUtil.getBaseUrl((HttpServletRequest)req), "");
if (rewriteConfig.ignoreUrl(url)){
chain.doFilter(req, resp);
}
else {
String location = rewriteConfig.getLocation(url);
String rewriteUrl = rewriteConfig.getUrl(location, url.replaceAll("/" + location + "/", ""));
if (rewriteUrl != null){
RequestDispatcher dispatcher = req.getRequestDispatcher(rewriteUrl);
dispatcher.forward(req, resp); // forward the request
}
else {
chain.doFilter(req, resp);
}
}
url is the requestUrl stripped of the host. This is so I can make it work on dev (http://localhost:8080/jtccom) and production (/).
This filter is called for every request, so I have an "ignore" map set up. This tests if the URL contains a ".", since every rewritten url will only contain numbers, letters, and the occasional "/" or "-". This is a HashMap for quick lookups. So, it won't attempt to rewrite calls to "/js/someFile.js".
The "location" part of the request is "/x/", so for news it will be "/news/". The location is "news". This is so I only have to loop through rewrite patterns for news, not for everything.
The pattern is written as "([0-9a-z-]+)/?" so if I pass in the whole URL (without the host), "/news/my-news-title", it won't match, so that's what the next line does, removes "/news/" so it's just "my-news-title". The getURL function returns the rewritten URL, so like "/news.jsf?title=my-news-title". I created a new unique column for News, and my "DaoWeb" interface has a "ChangeListener" property, so if I create a news or change it's title, it updates the "TitleKey" in this case. Pictures are just forwarded by their picture id for now, so
"/picture/23" as an example.
Coming soon: News by date span! /news/2008 for all news in 2008. /news/2008/03 for all news in March 2008! /news/2008/03/23 for all news on my birthday this year!!
Tune in for more updates. I'm cranking now, and Java is like riding a bike. I also fixed a few bugs.