Can I find the URL for a spring mvc controller in the view layer?
Asked Answered
S

6

18

I think what I need is called reverse url resolution in Django. Lets say I have an AddUserController that goes something like this:

@Controller
@RequestMapping("/create-user")
public class AddUserController{ ... }

What I want is some way to dynamically find the url to this controller or form a url with parameters to it from the view (JSP), so I don't have to hardcode urls to controllers all over the place. Is this possible in Spring MVC?

Stanger answered 4/7, 2009 at 18:34 Comment(1)
There can be cases where multiple urls maps to the same controller then what you want to do?Glossary
K
4

Since Spring 4 you can use MvcUriComponentsBuilder.

For the most type-safe method:

String url = fromMethodCall(on(MyController.class).action("param")).toUriString();

Note this example requires that the method returns a proxyable type - e.g. ModelAndView, not String nor void.


Since 4.2, the fromMappingName method is registered as a JSP function called mvcUrl:

<a href="${spring:mvcUrl('MyController#action').arg('param').build()}">Login</a>

This method does not have the proxy restriction.

Kennith answered 6/10, 2022 at 8:25 Comment(0)
C
2

Have you considered having a bean that aggregates all of the controller URLs you need into a HashMap and then adding this controller/URL Map to any model that requires it? Each Spring controller has the ability to call an init() method, you could have each controller add it's name and URL to the controller/URL map in the init() methods so it would be ready to use when the controllers go live.

Corydon answered 4/7, 2009 at 18:45 Comment(2)
I'll try making my own HandlerInterceptor that aggregates the controller->url mappings and ads them to every ModelAndView for every request. But still, this doesn't get even close to what is possible with django's url resolution and reverse resolution.Stanger
I see your point. Django nicely centralizes the url patterns even allowing names for them. I've jumped into the Spring source in the past to figure out how things get done, but its not a lot of funCorydon
K
2

Can solve with Java Reflection API. By Creating Custom Tag library. methods looks like this

Class c = Class.forName("Your Controller");

            for(Method m :c.getMethods()){
                if(m.getName()=="Your Method"){
                    Annotation cc = m.getAnnotation(RequestMapping.class);
                    RequestMapping rm = (RequestMapping)cc;
                    for(String s:rm.value()){
                        System.out.println(s);
                    }
                }
            }

Possible Problem You Can Face is

1.Path Variable > Like this /pet/show/{id} so set of path name & value should be support then replace this String.replace() before return url

2.Method Overriding > only one method is no problem. if Method override Need to give support sequence of Parameter Type That you really want like Method.getParametersType()

3.Multiple Url to Single Method> like @RequestMapping(value={"/", "welcome"}). so easy rule is pick first one.

4.Ant Like Style Url > Like this *.do to solve this is use multiple url by placing ant like style in last eg. @RequestMapping(value={"/pet","/pet/*.do"})


So Possible link tag style is

<my:link controller="com.sample.web.PetController" method="show" params="java.lang.Integer">
<my:path name="id" value="1" />
</my:link>

Where parmas attribute is optional if there is no method override.


May be I left to think about some problem. :)

Kora answered 25/11, 2010 at 17:9 Comment(0)
R
1

I would probably try to build a taglib which inspects the annotations you're using in order to find a suitable match:

<x:url controller="myController">
    <x:param name="action" value="myAction"/>
</x:url>

Taglib code might be something roughly like

  1. Ask Spring for configured beans with the @Controller annotation
  2. Iterate in some suitable order looking for some suitable match on the controller class or bean name
  3. If the @RequestMapping includes params, then substitute them
  4. Return the string

That might work for your specific case (@RequestMapping style) but it'll likely get a bit hairy when you have multiple mappings. Perhaps a custom annotation would make it easier.

Edit:

AbstractUrlHandlerMapping::getHandlerMap, which is inherited by the DefaultAnnotationHandlerMapping you're most likely using, returns a Map of URL to Handler

Return the registered handlers as an unmodifiable Map, with the registered path as key and the handler object (or handler bean name in case of a lazy-init handler) as value.

So you could iterate over that looking for a suitable match, where "suitable match" is whatever you want.

Renounce answered 12/8, 2009 at 15:30 Comment(0)
N
0

You can get access to the request object in any JSP file without having to manually wire in or manage the object into the JSP. so that means you can get the url path off the request object, have a google into JSP implicit objects.

Here is a page to get you started http://www.exforsys.com/tutorials/jsp/jsp-implicit-and-session-objects.html

Nutritionist answered 19/7, 2009 at 13:7 Comment(0)
F
0

The problem with this is that there's no central router in SpringMVC where all routes are registered and ordered. Then reverse routing is not a static process and route resolution in the view layer can be hard to integrate.

Check out this project for a centralized router (like rails) and reverse routing in the view layer.

Filip answered 14/10, 2012 at 10:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.