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.";
}
}
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.