Marek Urbanowicz
Marek Urbanowicz

Reputation: 13634

How to add "api" prefix to all controllers under one package com.myproject.api?

I was trying to find it but I found many different scenarios but not this one.

What I want to do is to add "/api/" prefix to all routes in controllers under com.myproject.api . I want "/api/*" for all controllers under package com.myapp.api and no prefix for all controllers under com.myapp.web

Is it possible with Spring / Spring Boot ?

Upvotes: 11

Views: 7294

Answers (5)

Multicolaure
Multicolaure

Reputation: 1038

With Spring Boot, this worked for me :

@Configuration
@EnableWebMvc
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/api",
               HandlerTypePredicate.forBasePackage("com.your.package"));
    }
}

Upvotes: 9

Andre Lubaczewski
Andre Lubaczewski

Reputation: 19

I achieved the result I think you are looking for in the following way, so long as you are using MVC.

First make a configuration class that implements WebMvcRegistrations

@Configuration
public class WebMvcConfig implements WebMvcRegistrations {

    @Value("${Prop.Value.String}") //"api"
    private String apiPrefix;

    @Value("${Prop.Package.Names}") //["com.myapp.api","Others if you like"]
    private String[] prefixedPackages;

    @Override
    public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
        return new PrefixedApiRequestHandler(apiPrefix,prefixedPackages);
    }
}

Then create a class that extends RequestMappingHandlerMapping and overrides getMappingForMethod

@Log4j2
public class PrefixedApiRequestHandler extends RequestMappingHandlerMapping {

    private final String prefix;

    private final String[] prefixedPackages;

    public PrefixedApiRequestHandler(final String prefix, final String... packages) {
        super();
        this.prefix = prefix;
        this.prefixedPackages = packages.clone();

    }

    @Override
    protected RequestMappingInfo getMappingForMethod(final Method method, final Class<?> handlerType) {

        RequestMappingInfo info = super.getMappingForMethod(method, handlerType);
        if (info == null) {
            return null;
        }

        for (final String packageRef : prefixedPackages) {
            if (handlerType.getPackageName().contains(packageRef)) {
                info = createPrefixedApi().combine(info);

                log.trace("Updated Prefixed Mapping " + info);
                return info;
            }
        }
        log.trace("Skipped Non-Prefixed Mapping " + info);
        return info;
    }

    private RequestMappingInfo createPrefixedApi() {
        String[] patterns = new String[prefix.length()];
        for (int i = 0; i < patterns.length; i++) {
            // Build the URL prefix
            patterns[i] = prefix;
        }

        return new RequestMappingInfo(
                new PatternsRequestCondition(patterns,
                        getUrlPathHelper(),
                        getPathMatcher(),
                        useSuffixPatternMatch(),
                        useTrailingSlashMatch(),
                        getFileExtensions()),
                new RequestMethodsRequestCondition(),
                new ParamsRequestCondition(),
                new HeadersRequestCondition(),
                new ConsumesRequestCondition(),
                new ProducesRequestCondition(),
                null);
    }
}

You should then see /api/(ControllerMapping) for all mappings, in the specified packages only. Note: I have @RequestMapping("/") at the top of my controller.

Upvotes: 1

xman_bsn
xman_bsn

Reputation: 67

If you are using springboot, you can add the following:

server.servlet.context-path=/api

to application.properties file.

Upvotes: 3

bekce
bekce

Reputation: 4310

You should add @RequestMapping("/api") to top of every desired @Controller or @RestController class.

When both the class and method have that annotation, Spring Boot appends them while building the url. In below example the method will be bound to /api/user route.

@RequestMapping("/api")
@RestController
public class MyController {

  @RequestMapping("/user")
  public List<User> getUsers(){
     return ...
  }

}

Upvotes: -1

Marc Tarin
Marc Tarin

Reputation: 3169

Already answered here and here.

Add an application.properties file under src/main/resources, with the following option:

server.contextPath=/api

Check the official reference for common properties.

Upvotes: -1

Related Questions