Search code examples
javaspring-mvcservlet-mapping

Spring MVC Servlet Mapping, differences between "/xxx" and "/xxx/*"


I am confused with how Spring MVC's url-pattern mapping works.

When 'getServletMappings' returns "/",I can get the right response with "http://localhost:8080/hello".

but not working if i change it to "/app" and change url to "http://localhost:8080/app/hello", it returns 404 error.

Am I misunderstanding something, I also find that "/app/*" can work(i can understand this), but why cannot "/app"?

Please check my code:

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected String[] getServletMappings() {
        // works with http://localhost:8080/hello
        return new String[] {
                "/"
        };
        // NOT working with http://localhost:8080/app/hello
        // return new String[] {
        //      "/app"
        //};
    }
}



@RestController
public class HTTPMethodsController {
   @RequestMapping("/hello")
   public String hello() {
       return "Hello SpringMVC.";
   }
}

Solution

  • According to the Servlet specification Chapter 12.2, the mapping of servlets must use the following syntax:

    • A string beginning with a ‘/’ character and ending with a ‘/*’ suffix is used for path mapping.
    • A string beginning with a ‘*.’ prefix is used as an extension mapping.
    • The empty string ("") is a special URL pattern that exactly maps to the application's context root, i.e., requests of the form application's context root, i.e., requests of the form http://host:port//. In this case the path info is ’/’ and the servlet path and context path is empty string (““).
    • A string containing only the ’/’ character indicates the "default" servlet of the application. In this case the servlet path is the request URI minus the context path and the path info is null.
    • All other strings are used for exact matches only.

    Therefore, mapping the DispatcherServlet with the URL "/app", causes the servlet container to route requests to it only when there is an exact match, meaning only if you change your url to "http://localhost:8080/app". That leaves no room for adding extra path to target specific Spring Controllers (to be more accurate: you could actually hit your hello() controller method if you mapped it with @RequestMapping("/app") because DispatcherServlet falls back to searching with the entire url, but practically that's not what you want).

    So the mapping "/app/*" is correct, or you could also map it as the default servlet with "/" as you noticed.