case nelson
case nelson

Reputation: 3667

How to determine Controller for given url (spring)

Using spring DefaultAnnotationHandlerMapping how can I lookup the Controller that would ultimately handle a given url.

I currently have this, but feels like there ought to be a cleaner way than iterating over 100s of request mappings:

public static Object getControllerForAction(String actionURL) {
    ApplicationContext context = getApplicationContext();
    AnnotationHandlerMapping mapping = (AnnotationHandlerMapping) context.getBean("annotationMapper");
    PathMatcher pathMatcher = mapping.getPathMatcher();
    for (Object key: mapping.getHandlerMap().keySet()) {
        if (pathMatcher.match((String) key, actionURL)){
            return mapping.getHandlerMap().get(key);
        }
    }
    return null;
}

Upvotes: 4

Views: 3657

Answers (3)

alvins
alvins

Reputation: 236

Above doesn't work in Spring 3.1. You can do the following instead.

Map<String, AbstractHandlerMethodMapping> map = WebApplicationContextUtils.getWebApplicationContext(servletContext).getBeansOfType(AbstractHandlerMethodMapping.class);
Iterator<AbstractHandlerMethodMapping> iter = map.values().iterator();
while (iter.hasNext()) {
    AbstractHandlerMethodMapping ahmb = iter.next();
    Iterator<Object> urls = ahmb.getHandlerMethods().keySet().iterator();
    while (urls.hasNext()) {
        Object url = urls.next();
        logger.error("URL mapped: " + url);
    }           
}

Upvotes: 3

skaffman
skaffman

Reputation: 403551

For the purposes of this question, all of the interesting methods in DefaultAnnotationHandlerMapping and its superclasses are protected, and so not visible to external code. However, it would be trivial to write a custom subclass of DefaultAnnotationHandlerMapping which overrides these methods and makes them public.

Since you need to be able to supply a path rather than a request object, I would suggest lookupHandler of AbstractUrlHandlerMapping would be a good candidate for this. It still needs you to supply it with a request object as well as the path, but that request object is only used to pass to the validateHandler() method, which does nothing, so you could probably supply a null there.

Upvotes: 3

ChssPly76
ChssPly76

Reputation: 100736

All mappers implement HandlerMapping interface which has a getHandler() method:

ApplicationContext context = getApplicationContext();
AnnotationHandlerMapping mapping = (AnnotationHandlerMapping) context.getBean("annotationMapper");
Object controller = mapping.getHandler().getHandler();

HandlerMapping.getHandler() returns HandlerExecutionChain, calling getHandler() on that would return you the actual handler which - for controller mapper - would be the controller you're looking for.

Upvotes: 2

Related Questions