Permit annotating packages via package-info.java with @RequestMapping to set the base path for controllers under a package and its sub-packages.

For example I have these packages:

  • com.example.laptops.controller.v1
  • com.example.laptops.controller.v2
  • com.example.tablets.controller.v1
  • com.example.tablets.controller.v2
  • com.example.phones.controller.v1
  • com.example.phones.controller.v2

Then:

  • I want to annotate com.example with @RequestMapping(path = "/store")
  • Annotate com.example.laptops with @RequestMapping(path = "/laptops")

That would turn the base path for all controllers in com.example.laptops.controller to /store/laptops.

Then I can annotate the com.example.laptops.controller.v1 package with v1 and the com.example.laptops.controller.v2 package with v2.

That would turn the base path for all controllers in com.example.laptops.controller.v1 to /store/laptops/v1 and the base path for all controllers in com.example.laptops.controller.v2 to /store/laptops/v2.

And so on.

Comment From: poutsma

Something to consider for 5.3

Comment From: rstoyanchev

This relates to #20883 which in turn supersedes #19231 and others. Those contain prior discussions on the topic. I admit the idea looks elegant but it is more convoluted when you consider that @RequestMapping is inherited from base classes and interfaces that can be from different packages which adds ambiguity.

20883 resulted in the external path prefix feature via WebFluxConfigurer for 5.1. I came up with the following for the above requirements:

@EnableWebMvc
public class MyWebConfig implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer conf) {
        Arrays.stream(Package.getPackages())
                .filter(p -> p.getName().startsWith("com.example"))
                .forEach(p -> conf.addPathPrefix(prefix(p), c -> c.getPackage().equals(p)));
    }

    private String prefix(Package p) {
        StringBuilder sb = new StringBuilder();
        if (p.getName().startsWith("com.example")) sb.append("/store");
        else if (p.getName().startsWith("com.example.laptops")) sb.append("/laptops");
        else if (p.getName().endsWith(".v1")) sb.append("/v1");
        else if (p.getName().endsWith(".v2")) sb.append("/v2");
        return sb.toString();
    }
}

Comment From: poutsma

After a team discussion, we decided that we will not implement this feature for the reason given by @rstoyanchev above. Moreover, the path prefix feature offers an alternative that does not break backward compatibility.