Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add "api" prefix to all controllers under 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 ?

like image 889
Marek Urbanowicz Avatar asked Mar 11 '17 08:03

Marek Urbanowicz


People also ask

How do you specify prefix for all controllers in spring boot?

Then, we only need to apply the annotation to each controller we want to prefix: @Controller @ApiPrefixController public class SomeController { @RequestMapping("/users") @ReponseBody public String getAll(){ // ... } }

Can we have multiple rest controllers in spring boot?

In Spring MVC, we can create multiple controllers at a time. It is required to map each controller class with @Controller annotation.

What is a controller REST API?

RestController is a Spring annotation that is used to build REST API in a declarative way. RestController annotation is applied to a class to mark it as a request handler, and Spring will do the building and provide the RESTful web service at runtime.


3 Answers

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

server.servlet.context-path=/api

to application.properties file.

like image 138
xman_bsn Avatar answered Oct 25 '22 14:10

xman_bsn


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"));
    }
}
like image 23
Multicolaure Avatar answered Oct 25 '22 15:10

Multicolaure


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.

like image 2
Andre Lubaczewski Avatar answered Oct 25 '22 16:10

Andre Lubaczewski