@PathVariable
| Since: | Spring Boot 3(2022) |
|---|
@PathVariable in Spring binds a portion of the URL path to a controller method argument. You write {variableName} in a path template such as @GetMapping("/{id}"), then annotate the corresponding method parameter with @PathVariable. Spring automatically converts the value found in the URL to the declared parameter type. This is commonly used in REST APIs to include a resource identifier — such as an ID or slug — directly in the URL.
Syntax
// Write {variableName} in the URL path template
@GetMapping("/path/{variableName}")
public ReturnType methodName(@PathVariable Type variableName) {
return responseData;
}
// If the parameter name differs from the template variable name, specify it with the value attribute
@GetMapping("/path/{id}")
public ReturnType methodName(@PathVariable("id") Long userId) {
return responseData;
}
// You can also receive multiple path variables at the same time
@GetMapping("/categories/{categoryId}/items/{itemId}")
public ReturnType methodName(
@PathVariable Long categoryId,
@PathVariable Long itemId) {
return responseData;
}
Attributes
| Attribute | Description |
|---|---|
| value / name | Specifies the name of the path template variable to bind, as a string. You can omit this attribute when the method parameter name matches the template variable name. |
| required | Specifies whether the path variable is required, as a boolean. The default is true. When set to false, the method also matches paths where the variable is absent, and the parameter receives null or an Optional. |
Sample Code
An example REST API that retrieves, updates, and deletes a user resource by ID.
package com.example.demo;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
// Register this class as a REST controller with @RestController
// Set the base path to /api/users with @RequestMapping
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// Handles GET /api/users/{id}
// The {id} value in the URL path is converted to Long and passed to the id parameter
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.findById(id);
if (user == null) {
// Return 404 if no matching user is found
return ResponseEntity.notFound().build();
}
// Return 200 with the user data if found
return ResponseEntity.ok(user);
}
// Handles PUT /api/users/{id}
// Receives the request body with @RequestBody and updates the user identified by id
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(
@PathVariable Long id,
@RequestBody UserRequest request) {
User updated = userService.update(id, request);
return ResponseEntity.ok(updated);
}
// Handles DELETE /api/users/{id}
// Returns 204 with no body on successful deletion
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
}
An example that combines multiple path variables to represent nested resources, such as categories and items.
package com.example.demo;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/categories")
public class ItemController {
private final ItemService itemService;
public ItemController(ItemService itemService) {
this.itemService = itemService;
}
// GET /api/categories/{categoryId}/items retrieves all items in the specified category
// {categoryId} is converted to Long and passed to the categoryId parameter
@GetMapping("/{categoryId}/items")
public List<Item> getItems(@PathVariable Long categoryId) {
return itemService.findByCategoryId(categoryId);
}
// GET /api/categories/{categoryId}/items/{itemId} retrieves details of a specific item
// Each of the two path variables is received by a separate parameter
@GetMapping("/{categoryId}/items/{itemId}")
public Item getItem(
@PathVariable Long categoryId,
@PathVariable Long itemId) {
return itemService.findByCategoryIdAndItemId(categoryId, itemId);
}
}
An example that uses required = false to define an optional path variable. This is useful in versioned APIs and similar scenarios.
package com.example.demo;
import java.util.Optional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/reports")
public class ReportController {
private final ReportService reportService;
public ReportController(ReportService reportService) {
this.reportService = reportService;
}
// Handles both GET /api/reports and GET /api/reports/{year} with a single method
// Setting required = false routes both paths to this method even when the variable is omitted
// Using Optional<Integer> allows safe null checking
@GetMapping({"", "/{year}"})
public String getReport(@PathVariable(required = false) Optional<Integer> year) {
if (year.isPresent()) {
// Return the report for the specified year
return reportService.getByYear(year.get());
}
// Return the latest report when the year is omitted
return reportService.getLatest();
}
}
How It Works
@PathVariable is Spring MVC's mechanism for automatically converting URL path template variables into method arguments. Many types are supported, including String, int, Long, and UUID. If conversion fails — for example, when a string is passed to a path that expects a number — Spring automatically returns a 400 Bad Request response.
When the method parameter name matches the path template variable name, you can omit the value attribute of @PathVariable. However, if the Java compiler option -parameters is not enabled (as in some older build configurations), parameter names may be lost at compile time. In that case, writing @PathVariable("id") explicitly is more reliable. Spring Boot 3 and later enable -parameters by default, so the shorthand form is safe to use.
To receive query strings (?key=value), use @RequestParam instead of a path variable. In common REST design practice, path variables are used for values that uniquely identify a resource (such as IDs or slugs), while query parameters are used for supplementary options like filtering or sorting.
For defining GET endpoints, see @GetMapping. For PUT endpoints, see @PutMapping. For DELETE endpoints, see @DeleteMapping.
If you find any errors or copyright issues, please contact us.