The @PathVariable annotation in Spring Framework extracts values from URI templates in HTTP requests. It enables dynamic path segments in URLs to be mapped to method parameters in controller methods. This article demonstrates using @PathVariable effectively in a Spring Boot application, focusing on the User entity.
@PathVariable Annotation
The @PathVariable annotation binds a method parameter to a path variable in the URL. This is particularly useful for creating RESTful web services where parts of the URL can be dynamically specified.
Basic Syntax:
@GetMapping("/users/{userId}")
public String getUser(@PathVariable("userId") String userId) {
return "User ID is: " + userId;
}In this example, {userId} in the URL is mapped to the userId parameter in the method.
Example of Spring @PathVariable Annotation
1. Basic @PathVariable Usage:
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")
public class UserController {
@GetMapping("/users/{userId}")
public String fetchUserById(@PathVariable("userId") Long userId) {
return "Retrieved User ID: " + userId;
}
}
Explanation:
@RestController: Marks the class as a REST controller, combining@Controllerand@ResponseBody, meaning that the return values of methods will be written directly to the HTTP response body.@RequestMapping("/api"): Sets the base URL for all endpoints in this controller to/api.@GetMapping("/users/{userId}"): Maps HTTP GET requests with/users/{userId}to thefetchUserByIdmethod.@PathVariable("userId"): Binds the{userId}path variable from the URL to theuserIdmethod parameter.
Expected Output:
- For a request to
/api/users/123, the output would be:"Retrieved User ID: 123"
Note: To know how test the APIs using Postman Tool, refer to this article: Testing REST API with Postman
2. Handling Optional Path Variables
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;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users/{userId}/{userName}")
public String fetchUserDetails(@PathVariable Map<String, String> pathVariables) {
String userId = pathVariables.get("userId");
String userName = pathVariables.get("userName");
if (userId != null && userName != null) {
return "User ID: " + userId + ", Name: " + userName;
} else {
return "Parameters are missing";
}
}
}
Explanation:
@PathVariable(name = "postId", required = false): Marks thepostIdpath variable as optional. IfpostIdis not provided in the URL, it will benull.
Expected Output:
- For a request to
/api/users/123/posts/456, the output would be:"User ID: 123 and Post ID: 456" - For a request to
/api/users/123/posts, the output would be:"User ID: 123 with no post specified."
3. Handling Multiple @PathVariable Parameters
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;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users/{userId}/{userName}")
public String fetchUserDetails(@PathVariable Map<String, String> pathVariables) {
String userId = pathVariables.get("userId");
String userName = pathVariables.get("userName");
if (userId != null && userName != null) {
return "User ID: " + userId + ", Name: " + userName;
} else {
return "Parameters are missing";
}
}
}
Explanation:
@PathVariable Map<String, String> pathVariables: Binds all path variables to aMap. The keys of the map are the path variable names, and the values are the path variable values.
Expected Output:
- For a request to
/api/users/123/john, the output would be:"User ID: 123, Name: john" - For a request with missing parameters, the output would be:
"Parameters are missing"
4. Basic Mapping for Class and Method Levels
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/users")
public class UserController {
@GetMapping("/details/{userId}/{userName}")
public String retrieveUserDetails(@PathVariable("userId") String userId, @PathVariable("userName") String userName) {
return "ID: " + userId + ", Name: " + userName;
}
}
Explanation:
@RequestMapping("/api/users"): Sets the base URL for all endpoints in this controller to/api/users.@GetMapping("/details/{userId}/{userName}"): Maps HTTP GET requests with/details/{userId}/{userName}to theretrieveUserDetailsmethod.
Expected Output:
- For a request to
/api/users/details/123/john, the output would be:"ID: 123, Name: john"
5. Including Default Values for Path Variables
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")
public class UserController {
@GetMapping({ "/users/required", "/users/required/{userId}" })
public String getUserById(@PathVariable(required = false) String userId) {
if (userId != null && !userId.isEmpty()) {
return "User ID: " + userId;
} else {
return "User ID is missing";
}
}
}
Explanation:
@PathVariable(required = false): Makes theuserIdpath variable optional. If not provided, a default message is returned.
Expected Output:
- For a request to
/api/users/required/123, the output would be:"User ID: 123" - For a request to
/api/users/required, the output would be:"User ID is missing"
6. Creating a Default Value for @PathVariable
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;
import java.util.Optional;
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping({ "/default/optional", "/default/optional/{id}" })
public String fetchUserWithOptionalId(@PathVariable Optional<String> id) {
return id.map(value -> "User ID: " + value)
.orElse("User ID: Default User");
}
}
Explanation:
@PathVariable Optional<String> id: UsesOptionalto handle the presence or absence of the path variableid. Ifidis not present, a default value is used.
Expected Output:
- For a request to
/api/users/default/optional/123, the output would be:"User ID: 123" - For a request to
/api/users/default/optional, the output would be:"User ID: Default User"
Conclusion
This article provides a comprehensive overview of the @PathVariable annotation, complete with explanations and expected output for each code example, specifically designed for managing User entities.