user4903
user4903

Reputation:

In a servlet mapping in Spring MVC how do I map the root of a url pattern directory?

<servlet-mapping>
    <servlet-name>testServlet</servlet-name>
    <url-pattern>/test/*</url-pattern>
</servlet-mapping>

If I hit /test/page the above will work. However, hitting /test or /test/ will not work. I'm using Spring MVC, and my request mapping is as follows:

@RequestMapping(value = {"","/"})

EDIT:

I'm in the process of verifying with an independent project, but this appears to be a bug with Spring's UrlPathHelper. The following method returns an incorrect path when there is both a context and a servlet path, and you hit the servlet without a trailing slash.

public String getPathWithinApplication(HttpServletRequest request) {
    String contextPath = getContextPath(request);
    String requestUri = getRequestUri(request);
    if (StringUtils.startsWithIgnoreCase(requestUri, contextPath)) {
        // Normal case: URI contains context path.
        String path = requestUri.substring(contextPath.length());
        return (StringUtils.hasText(path) ? path : "/");
    }
    else {
        // Special case: rather unusual.
        return requestUri;
    }
}

Just as an example let's say I have a context of "admin" and the following servlet-mapping:

<servlet-mapping>
    <servlet-name>usersServlet</servlet-name>
    <url-pattern>/users/*</url-pattern>
</servlet-mapping>

Now I have a request mapping in one of my controllers like this:

@RequestMapping(value = {"","/"})

If I hit /admin/users it will not work. However, if I hit /admin/users/ it will work. Now if I change my request mapping to the following then they will both work:

@RequestMapping(value = {"/users","/"})

However, now the URL /admin/users/users will also work (which is not what I would want).

Upvotes: 10

Views: 23101

Answers (5)

Matt Sgarlata
Matt Sgarlata

Reputation: 1847

Yevgeniy is correct, but if your DispatcherServlet is taking over for the default servlet, you have to add this to your web.xml:

<welcome-file-list>
    <welcome-file>/</welcome-file>
</welcome-file-list>

Upvotes: 5

Georgios Syngouroglou
Georgios Syngouroglou

Reputation: 19944

In my case, every url was working except of the root "/" url.
The problem was that i didn't deleted the index.htm file inside of my projects' webapp root folder.

Upvotes: 0

Daniel De Le&#243;n
Daniel De Le&#243;n

Reputation: 13649

A way without touch the web.xml file is by set the map to the default welcome file path.

@RequestMapping("/index.html")

Upvotes: 0

Yevgeniy
Yevgeniy

Reputation: 2694

my setup usually looks like this:

<servlet-mapping>
    <servlet-name>testServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

controller, where i assume you want to handle /test and /test/ equally:

@Controller
public class MyController {

    @RequestMapping("/test")
    public String test() {
        return "redirect:/welcome";
    }

    @RequestMapping("/test/")
    public String test() {
        return "redirect:/welcome";
    }

    @RequestMapping("/welcome")
    public void test(ModelMap model) {
        // do your stuff
    }
}

setup like this would cause DispatcherServlet to handle requests for *.css and *.js files, which is not desired in most cases. i think this is the problem Bhavik describes. For those resources you can you the ResourceController like this:

<mvc:resources mapping="/css/**" location="/resources/css/" />
<mvc:resources mapping="/js/**" location="/resources/js/" />

files from /resources/css and /resources/js will be served without forcing you to write a extra controller.

Upvotes: 3

Bhavik Ambani
Bhavik Ambani

Reputation: 6657

First of all, the difference between mapping dispatcher servlet to "/" and to "/*". There is a difference!

When mapping to "/*", all URL requests (including something like this "/WEB-INF/jsp/.../index.jsp") are mapped to dispatcher servlet.

Secondly, when using Spring + Tiles, and returning some JSP in your tiles definition, it is treated as an internal forward request, and handled by the same servlet as the original request. In my example, I invoke root URL "/", which is properly caught by home() method, and then forwarded to "index.jsp" by Tiles, which is again being handled by Dispatcher Servlet. Obviously, dispatcher servlet cannot handle "index.jsp", because there is no controller for it.

Yeah, it is ugly, but looks like this is the way it works.

So, the only solution I've found so far: to change "/*" back to "/" in web.xml. This way JSPs are rendered properly by Tomcat's jsp servlet, I guess, and not dispatcher servlet. Unfortunately, this fix will break the ROOT URL dispatching by Spring, so you need to leave the idea of using ROOT URL + Tiles for now.

Please note that adding explicit servlet mapping ".jsp -> Tomcat jsp in web.xml doesn't help, when using "/*", and it sucks.

Still the problem is not resolved.

Also this is the problem in Spring MVC 3.0

Upvotes: 2

Related Questions