Results 1 to 5 of 5

Thread: URL and parameter

  1. #1
    Join Date
    Jul 2006
    Location
    New York, NY
    Posts
    9

    Default URL and parameter

    Has anyone had any experience of customizing Spring MVC to allow for pretty, search-engine friendly URLS like:

    http://mywebsite.com/blog/2004/11/2002/post.html

    Of course SimpleUrlHandlerMapping can already handle resolving the path to the right controller (with some help from org.springframework.web.util.UrlPathHelper)

    Code:
    	<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    		<property name="mappings">            
    			<props>
    				<prop key="/*/*/*/post.html">blogController</prop>
    			</props>
    		</property>  
    	</bean>
    I could go ahead and do something kludgy by including some sort of code to parse request.getPathInfo() and set request attributes appropriately - but this, to me seems a dirty and inelegant way of doing things.

    What would seem more elegant would be to extract parameters from the */*/* request path, and then use a custom binder to allow for them to be bound to a command object.

    Has anyone out there written their own binder to handle this sort of thing? If anyone's interested in working on this together I'm definitely up for creating something along these lines. I have a couple user-facing applications that will benefit greatly from clean, easy-to-remember, SEF Urls.

  2. #2
    Join Date
    Oct 2004
    Posts
    17

    Default RE: url and parameter

    Hi,

    I'm working on a similar problem. My webapp is based on Spring 1.2.8, and currently uses URLs like:

    http://myapp.example.com/user/projects/view.html?projectId=1024

    I'd like to change the URL scheme so that the resource at the URL above would be available at the URL below:

    http://myapp.example.com/user/projects/1024

    My solution for extracting identifiers from the URL uses regular expressions with groups:

    Code:
    Pattern pattern = Pattern.compile("/user/projects/(\\d*)/?$");
    Matcher matcher = pattern.matcher(request.getServletPath() + request.getPathInfo());
    long projectId = Long.parseLong(m.group(1));
    By changing the regex pattern, you can easily extract as many embedded parameters as you need.

    On the other side of things, when a controller's response needs to redirect the browser back to a URL with identifiers (e.g. after successfully editing a project, redirect back to view that project), it uses org.springframework.web.servlet.view.RedirectView for generation of URLs, passing in a model with name/value pairs (e.g. model.put("projectId", id)). The problem is that these model values are appended as HTTP querystring paramters. For these cases, I created a new org.springframework.web.servlet.View implementation (extends org.springframework.web.servlet.view.AbstractUrlBa sedView) that behaves just like RedirectView, but uses java.text.MessageFormat to insert values into a template URL:

    Code:
    	protected void renderMergedOutputModel(Map model, HttpServletRequest request,
    			HttpServletResponse response) throws Exception {
    		// prepare target URL
    		StringBuffer targetUrl = new StringBuffer();
    		if (getUrl().startsWith("/")) {
    			targetUrl.append(request.getContextPath());
    		}
    		MessageFormat format = new MessageFormat("/user/projects/{0}");
    		targetUrl.append(format.format(model.values().toArray()));
    		response.sendRedirect(response.encodeRedirectURL(targetUrl.toString()));
    	}
    This all works, but there are several concerns:

    1. Using regular expressions might be overkill for such simple URL parsing.
    2. I've put the regular expression logic into a helper class; the controller constructs a member instance with the regex pattern, and then calls a method for each parameter it needs to extract from the URL. To keep it thread-safe, the Matcher must be instantiated again for each method call. In my particular case, it's unlikely that my controllers will need to extract more than two or three parameters from the URL, but is there reason to be concerned about object creation and the ensuing gargabe collection? Is Matcher a heavyweight object?
    3. I might also want to extract parameters from the URL in an interceptor, but this requires additional regular expression objects. This results in more object creation for the additional Pattern and Matcher instances.
    4. My RedirectView implementation converts the incoming model map to an object array in order to insert the values into the target URL. If the model is an unsorted Map, then the ordering of those values is undetermined. If you have only one value, it doesn't matter. But with multiple values, you have to use a sorted map; otherwise the values may be inserted into the wrong places. This smacks of bad design.


    Another approach for extraction would be an interceptor that simply parses the URL path components into string array or collection (could be as simple as java.lang.String.split(regex)), and put that collection into the request as an attribute. Controllers would presumably know which component represented which identifier, and could then retreive the correct component (converting to the appropriate datatype as necessary). I don't have any other ideas for the redirection issue, though.

    I checked Spring 2.0 for better solutions, but didn't see anything. Maybe I missed something. Any better ideas out there?

  3. #3

    Default

    If you are running on Apache, .htaccess can easily handle the URL changing that you describe

  4. #4
    Join Date
    Jun 2005
    Posts
    4,241

    Default

    What's wrong with using regular expressions? It looks like a perfectly valid approach to me. If the overhead in regexp matching is all you have to worry about your will be fortunate, but you can save some overhead by caching the compiled Pattern (since it is constant). You could use a ViewResolver or an Interceptor that binds stuff into the model. I don't think any of the issues mentioned with the model are really problematic - what's wrong with SortedMap anyway?.

  5. #5
    Join Date
    Jul 2006
    Posts
    24

    Default

    I think Daniel was trying to point out that it could be done with apache's mod_rewrite functionality which itself is a regular expression engine. The nice thing is you, potentially, wouldn't have to change your code to work with the pretty URLs.

    http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html

    Of course, your program then depends on Apache and part of your configuration is now outside of Spring.
    Last edited by digerata; Oct 27th, 2006 at 12:45 PM. Reason: typos

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •