5

Let's say we have 3 url-patterns for a servlet named dispatcher in web.xml:

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/aaa/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/bbb/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/ccc/*</url-pattern>
</servlet-mapping>

and a controller method:

@RequestMapping(value = "/xxx", method = RequestMethod.POST)
public String foo() {}

Since the path value in @RequestMapping does not contain servlet path, when users request

/aaa/xxx
/bbb/xxx
/ccc/xxx

the requests will all be mapped to method foo.

I think this could cause potential problem if the web site is very complicated. Is it a flaw in Spring Web MVC or I misunderstand something?

user2418306
  • 2,352
  • 1
  • 22
  • 33
PickBoy
  • 1,234
  • 1
  • 13
  • 20
  • You mapped all three paths to the same servlet, called "dispatcher". – Stefan Mar 18 '16 at 07:33
  • For those who find here by googling, I think the answers of this question: http://stackoverflow.com/questions/11692837/url-mapping-issue-spring-web-mvc solved my problem. – PickBoy Jan 15 '17 at 11:33

2 Answers2

9

You can map all requests to one request mapping by passing multiple value.

@RequestMapping(value = {"/aaa/xxx", "/bbb/xxx", "/ccc/xxx"}, method = RequestMethod.POST)
public String foo() {}

and just change mapping in web.xml to handle all type of request to dispatcher servlet.

<servlet-mapping>
   <servlet-name>dispatcher</servlet-name>
   <url-pattern>/*</url-pattern>
</servlet-mapping>

You can define different controllers based on application requirement or web flow. You can move common piece of code in utility classes if needed.

@RequestMapping("/aaa")
public class AAAController {
    @RequestMapping(value = "/xxx", method = RequestMethod.POST)
    public String foo() {
        // call to common utility function
    }
    // other methods
}

@RequestMapping("/bbb")
public class BBBController {
    @RequestMapping(value = "/xxx", method = RequestMethod.POST)
    public String foo() {
        // call to common utility function
    }
    // other methods
}

@RequestMapping("/ccc")
public class CCCController {
    @RequestMapping(value = "/xxx", method = RequestMethod.POST)
    public String foo() {
        // call to common utility function
    }
    // other methods
}

Read more in Spring Web MVC framework documentation

You can configure it programatically as well

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping("/*");
    }
}
Braj
  • 46,415
  • 5
  • 60
  • 76
  • 1
    Thanks for you reply! Actually I don't want multiple types of requests to be mapped to the same controller method. I think the solution you mentioned (change url-mapping to "/*" ) could solve the problem, but then I wonder what's the point of url-pattern in servlet configuration, since most people will set it to "/*" anyway? – PickBoy Mar 18 '16 at 07:59
  • It's common use case for spring web application where `dispatcher` servlet works as front servlet that's responsibility to consult with handler mapping and forward the request to the correct controller. You just need to configure handler mapping for different url in separate spring configuration file instead of doing it in `web.xml`. – Braj Mar 18 '16 at 08:01
  • 1
    Please read about different implementation of [handler mapping](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/HandlerMapping.html) – Braj Mar 18 '16 at 08:04
0

I had a situation where I cannot use /* mapping to dispatcher servlet, because I don't want all my requests of static resources to go to dispatcher servlet. So I used the below mapping to dispatcher servlet

<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/spring/*</url-pattern>
</servlet-mapping>

and append the /spring to all your urls ex. http://localhost:8080/context/spring/common/get/currentuser

and your controller will look like below

@RestController

@RequestMapping("/common")

public class CommonController extends BaseController {

@RequestMapping(method = RequestMethod.GET,value="/get/currentuser")
public @ResponseBody User getUser() throws Exception  {
            // implementation ...

}


}


}
akarahman
  • 235
  • 2
  • 15