Reputation: 13634
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
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
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
Reputation: 67
If you are using springboot, you can add the following:
server.servlet.context-path=/api
to application.properties file.
Upvotes: 3
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
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