|
| 1 | +{ |
| 2 | + "id": 110, |
| 3 | + "slug": "spring-api-versioning", |
| 4 | + "title": "Spring Framework 7 API Versioning", |
| 5 | + "category": "enterprise", |
| 6 | + "difficulty": "intermediate", |
| 7 | + "jdkVersion": "17", |
| 8 | + "oldLabel": "Spring Boot 2/3", |
| 9 | + "modernLabel": "Spring Framework 7+", |
| 10 | + "oldApproach": "Manual URL Path Versioning", |
| 11 | + "modernApproach": "Native API Versioning", |
| 12 | + "oldCode": "// Version 1 controller\n@RestController\n@RequestMapping(\"/api/v1/products\")\npublic class ProductControllerV1 {\n @GetMapping(\"/{id}\")\n public ProductDtoV1 getProduct(\n @PathVariable Long id) {\n return service.getV1(id);\n }\n}\n\n// Version 2 — duplicated structure\n@RestController\n@RequestMapping(\"/api/v2/products\")\npublic class ProductControllerV2 {\n @GetMapping(\"/{id}\")\n public ProductDtoV2 getProduct(\n @PathVariable Long id) {\n return service.getV2(id);\n }\n}", |
| 13 | + "modernCode": "// Configure versioning once\n@Configuration\npublic class WebConfig implements WebMvcConfigurer {\n @Override\n public void configureApiVersioning(\n ApiVersionConfigurer config) {\n config.useRequestHeader(\"X-API-Version\");\n }\n}\n\n// Single controller, version per method\n@RestController\n@RequestMapping(\"/api/products\")\npublic class ProductController {\n @GetMapping(value = \"/{id}\", version = \"1\")\n public ProductDtoV1 getV1(@PathVariable Long id) {\n return service.getV1(id);\n }\n\n @GetMapping(value = \"/{id}\", version = \"2\")\n public ProductDtoV2 getV2(@PathVariable Long id) {\n return service.getV2(id);\n }\n}", |
| 14 | + "summary": "Replace duplicated version-prefixed controllers with Spring Framework 7's native API versioning support.", |
| 15 | + "explanation": "Before Spring Framework 7, API versioning required separate controller classes per version (e.g., /api/v1/products, /api/v2/products), duplicating request mappings and scattering version logic across many files. Spring Framework 7 introduces native versioning through a new version attribute on @RequestMapping and related annotations, plus a configureApiVersioning hook in WebMvcConfigurer. The version can be resolved from a request header, a URL path segment, or a query parameter — all controlled in one place.", |
| 16 | + "whyModernWins": [ |
| 17 | + { |
| 18 | + "icon": "🗂️", |
| 19 | + "title": "No controller duplication", |
| 20 | + "desc": "All versions live in one controller class; only the individual handler methods carry a version attribute." |
| 21 | + }, |
| 22 | + { |
| 23 | + "icon": "⚙️", |
| 24 | + "title": "Centralised version strategy", |
| 25 | + "desc": "Switch from header to URL or query-param versioning in a single configureApiVersioning call." |
| 26 | + }, |
| 27 | + { |
| 28 | + "icon": "📈", |
| 29 | + "title": "Incremental evolution", |
| 30 | + "desc": "Add a new version to one method without touching unrelated endpoints or creating new controller files." |
| 31 | + } |
| 32 | + ], |
| 33 | + "support": { |
| 34 | + "state": "available", |
| 35 | + "description": "Available since Spring Framework 7.0 (requires Java 17+)" |
| 36 | + }, |
| 37 | + "prev": "enterprise/jdbc-resultset-vs-jpa-criteria", |
| 38 | + "next": null, |
| 39 | + "related": [ |
| 40 | + "enterprise/soap-vs-jakarta-rest", |
| 41 | + "enterprise/servlet-vs-jaxrs", |
| 42 | + "enterprise/ejb-vs-cdi" |
| 43 | + ], |
| 44 | + "docs": [ |
| 45 | + { |
| 46 | + "title": "Spring Framework 7.0 — API Versioning", |
| 47 | + "href": "https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-requestmapping.html#mvc-ann-requestmapping-version" |
| 48 | + }, |
| 49 | + { |
| 50 | + "title": "Spring Framework 7.0 Migration Guide", |
| 51 | + "href": "https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-7.0-Migration-Guide" |
| 52 | + } |
| 53 | + ] |
| 54 | +} |
0 commit comments