7 Ways to Add a Unified Prefix to Spring Boot Controllers

This article explains why a common API prefix (e.g., /api/v1) is useful in microservice or front‑back separation projects and demonstrates seven practical techniques—custom DispatcherServlet registration, YAML configuration, SpEL‑based @RequestMapping, custom composed annotation, WebMvcConfigurer addPathPrefix, internal forwarding, Spring Cloud Gateway ProxyExchange, and Nginx reverse proxy—using Spring Boot 3.5.0 examples and code snippets.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
7 Ways to Add a Unified Prefix to Spring Boot Controllers

1. Introduction

In microservice architectures or front‑back separated projects, adding a uniform prefix such as /api/v1 to controller endpoints is a standard best practice. It supports API versioning, simplifies gateway routing and security configuration, and separates dynamic API paths from static front‑end resources.

2. Implementation Examples (Spring Boot 3.5.0)

2.1 Custom DispatcherServlet Registration

@Configuration
public class ServletConfig {
  @Bean
  public DispatcherServletRegistrationBean dispatcherServletRegistration(
      DispatcherServlet dispatcherServlet,
      WebMvcProperties webMvcProperties,
      ObjectProvider<MultipartConfigElement> multipartConfig) {
    DispatcherServletRegistrationBean registration =
        new DispatcherServletRegistrationBean(dispatcherServlet, "/api/");
    registration.setName("dispatcherServlet");
    registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
    multipartConfig.ifAvailable(registration::setMultipartConfig);
    return registration;
  }
}

All controller mappings will now be accessed under the /api/** prefix.

2.2 Configuration File

spring:
  mvc:
    servlet:
      path: /api

Setting the servlet path in application.yml automatically prefixes every request.

2.3 SpEL‑Based @RequestMapping

Define a property and use Spring Expression Language in the mapping:

@RestController
@RequestMapping(path = "${pack.app.apiPrefix}/users")
public class UserController {
    // ...
}
pack:
  app:
    api-prefix: /api

This approach requires modifying each controller but keeps the prefix configurable.

2.4 Custom Composed Annotation

@RequestMapping(value = "/api/")
public @interface PackMapping {}

// Usage
@RestController
@PackMapping
public class UserController {
    @RequestMapping("/users")
    public String getAll() {
        return "...";
    }
}

A custom annotation abstracts the prefix, making it reusable and concise.

2.5 WebMvcConfigurer addPathPrefix

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("/api", clazz -> true);
    }
}

The addPathPrefix method adds the prefix to all controller classes; the predicate can be refined for selective application.

2.6 Internal Forwarding (Custom Routing)

@RestController
public class EndpointController {
    @GetMapping("/endpoint1")
    public String endpoint1() { return "..."; }
    @GetMapping("/endpoint2")
    public String endpoint2() { return "..."; }
}

@Controller
@RequestMapping("/api/endpoint")
public class ApiPrefixController {
    @GetMapping
    public ModelAndView route(ModelMap model, HttpServletRequest request) {
        String action = request.getHeader("X-ACTION");
        return switch (action) {
            case null -> new ModelAndView("forward:/error");
            case "xxx" -> new ModelAndView("forward:/endpoint1", model);
            case "zzz" -> new ModelAndView("forward:/endpoint2", model);
            default -> new ModelAndView("forward:/home");
        };
    }
}

This method forwards requests server‑side without involving the client, preserving the original request flow.

2.7 Spring Cloud Gateway ProxyExchange

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-gateway-proxyexchange-webmvc</artifactId>
  <version>4.3.5</version>
</dependency>
@RestController
public class GatewayController {
    @GetMapping("/api/{*path}")
    public Object proxy(ProxyExchange<Object> proxy, HttpServletRequest request) throws Exception {
        String targetURI = proxy.path("/api");
        URI uri = ServletUriComponentsBuilder.fromServletMapping(request)
                .path(targetURI)
                .build()
                .toUri();
        return proxy.uri(uri).get();
    }
}

The example handles GET requests; POST and other methods can be added similarly.

2.8 Nginx Reverse Proxy

server {
  listen 80;
  server_name default;
  location /api/ {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://www.pack.com;
  }
}

This configuration forwards all /api/** requests to the backend without modifying application code.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSpring BootNGINXcontrollergatewayspring-mvcapi-prefix
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.