Spring @PathVariable

Learn how @PathVariable works in Spring Boot with RESTful URL design, resource IDs, UUID path variables, validation, and API examples.

Last reviewed: November 2026

·Spring Boot 2.7Spring Boot 3.x
✅
Quick Understanding: @PathVariable is the Spring Boot annotation used to read values from URL path segments such as `/users/{id}` or `/orders/{orderId}`. Use it when the URL identifies a specific resource, not when you are filtering or paginating results.

🔍 What Is It?

@PathVariable binds a URI template variable to a method parameter.

Syntax:

  • →Define a template variable: @GetMapping("/users/{id}")
  • →Bind it: @PathVariable("id") Long id
  • →Or with explicit name: @PathVariable("id") Long userId

Supported types:

  • →String, int, long, Integer, Long
  • →UUID, LocalDate
  • →Other types supported by the configured conversion service; register a converter for a custom identifier when needed

Use an explicit annotation name even when it matches the Java parameter. Omitting it relies on retained parameter-name metadata, such as compilation with -parameters; parameter-name discovery changed in Spring Framework 6.1.

Request outcomes

RequestMapping and parameterTypical result
GET /users/42/users/{id}, Long idid is 42
GET /users/abc/users/{id}, Long id400 from type conversion
GET /usersOnly /users/{id} existsMapping does not match; normally 404 if no other handler matches
GET /users/42Conversion succeeds, service finds no userApplication must return the appropriate response, usually 404

Conversion is separate from existence and authorization. A valid ID or UUID does not prove the caller can access the resource. A negative Long also converts successfully; enforce domain constraints separately.

Multiple path variables:

@GetMapping("/users/{userId}/orders/{orderId}")
public OrderDto getOrder(
    @PathVariable("userId") Long userId,
    @PathVariable("orderId") Long orderId) { ... }

🎯 Why Do We Need It?

RESTful API design uses URL paths to identify resources directly. /users/42 is clearer and more semantic than /users?id=42 when the request is about one specific entity. @PathVariable makes resource identification explicit in the URL structure and keeps Spring Boot controller mappings aligned with REST conventions.

🏗️ What Happens in Real Projects?

Every CRUD API uses path variables for resource identification:

  • →GET /api/v1/orders/{orderId} — get specific order
  • →PUT /api/v1/users/{userId}/roles/{roleId} — assign role to user
  • →DELETE /api/v1/products/{productId} — delete product
  • →GET /api/v1/categories/{categorySlug}/products — products in category

⚙️ How It Works

Spring first matches the request path against the mapping, then resolves each URI variable by name and converts the captured text to the declared Java type. A conversion failure normally produces a 400 response before the controller body runs. Once conversion succeeds, the application still needs to perform domain validation, lookup, and access checks.

Optional path variables

required = false changes argument resolution; it does not make a missing URL segment match an existing pattern. Map both /users and /users/{id} if the same handler intentionally accepts both. Use a wrapper type or Optional for the missing value.

Dates and slash-containing paths

Use an explicit date format for a LocalDate argument. A normal {id} captures one path segment. Multi-segment capture such as {*path} depends on the configured PathPattern matching strategy and belongs at the end of a pattern; it is not an optional-segment syntax.

💻 Example

Path Variables in Practice — Single, multiple, and optional path variables.

java
import java.time.LocalDate;
import java.util.UUID;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PathVariableDemoController {
    @GetMapping("/users/{id}")
    public String user(@PathVariable("id") Long userId) {
        return "User " + userId;
    }

    @GetMapping("/sessions/{id}")
    public String session(@PathVariable("id") UUID sessionId) {
        return sessionId.toString();
    }

    @GetMapping("/reports/{day}")
    public String report(@PathVariable("day")
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate day) {
        return day.toString();
    }

    @GetMapping({"/optional-users", "/optional-users/{id}"})
    public String optionalUser(@PathVariable(name = "id", required = false) Long id) {
        return id == null ? "All users" : "User " + id;
    }
}

// GET /users/42             -> User 42
// GET /users/abc            -> 400 with standard Spring MVC error handling
// GET /reports/2026-11-01   -> 2026-11-01
// GET /optional-users      -> All users
// GET /optional-users/42   -> User 42

🤔 Common Confusions

❓ What if the path variable doesn't match the method parameter name?

Use @PathVariable("urlVariableName") Type methodParamName. Example: @GetMapping("/users/{user_id}") with @PathVariable("user_id") Long userId. The names must match when you omit the annotation value — Spring uses the parameter name by default.

❓ Can path variables be optional?

Yes, with required=false: @PathVariable(required=false) Long id. But this requires two mappings: one with the variable and one without. Better approach: use two separate methods with different @GetMapping paths, or use @RequestParam for optional identifiers.

🚨 Common Production Issues

Path variable not validated — a negative or zero ID reaching the database; add @Positive validation

String path variable containing SQL injection attempts — never use path variables directly in SQL strings

UUID path variable causing 400 errors for invalid UUID format — handle MethodArgumentTypeMismatchException

✅ Best Practices

Use Long or UUID for IDs — not String (prevents type mismatch errors reaching your service)

Validate path variable values: @PathVariable @Positive Long id

Handle MethodArgumentTypeMismatchException in your global exception handler

Use semantic slugs for public-facing APIs (/products/iphone-15-pro) instead of numeric IDs

🏛️ Architect's Note

Senior Architect's Perspective

Choose identifiers according to the resource contract. UUIDs can make guessing identifiers harder, but do not replace authorization. For a nested URL such as /users/{userId}/orders/{orderId}, verify both that the order belongs to that user and that the caller may access it. Human-readable slugs can help public navigation, but need an explicit strategy when names change.

💬 Frequently Asked Questions

How do I handle a path variable that contains slashes?

A regular URI variable matches one segment. With PathPattern matching, a final capture such as /files/{*path} can capture multiple segments; verify the configured matching strategy. Avoid manually splitting the raw request URI. If mapping a capture to a file, normalize and authorize it within the intended storage boundary rather than passing arbitrary text directly to file access.

What is the difference between @PathVariable and @RequestParam?

@PathVariable is for values that identify a resource in the URL path like `/users/{id}`, while @RequestParam is for query-string values that filter, sort, paginate, or slightly change retrieval like `/users?page=0&role=ADMIN`.

Can Spring Boot auto-convert UUID path variables?

Yes. Spring Boot can automatically convert a valid UUID string in the URL into a `UUID` method parameter when you declare `@PathVariable UUID sessionId` or a similar type.

Why does my path variable return a 400 response?

First compare the captured value with the declared type. Values such as abc cannot convert to Long, and malformed UUIDs fail conversion. Custom validation can also reject values. Check the exception and distinguish a conversion failure from a resource lookup that returns no result.

Does required=false make a URL segment optional?

No. It permits a missing argument after a handler has been matched. To handle both /users and /users/{id}, declare both mappings or separate handlers. Use Long or Optional<Long> when the variable may be absent, not a primitive long.

Why specify the name in @PathVariable explicitly?

An explicit name connects the annotation directly to the URI template and avoids relying on compiler-retained parameter names. For example, /users/{id} can bind to @PathVariable("id") Long userId even though the Java parameter has a different name.

Does a valid UUID mean the user is authorized?

No. Type conversion only establishes that the value can be represented as a UUID. The service must still check resource existence, ownership, and caller permissions. An unguessable identifier is not an access-control mechanism.

🎯 Key Takeaways

1@PathVariable extracts values from URL path segments: /users/{id}
2Spring auto-converts path variables to Long, UUID, enum, etc.
3Path variables identify resources; query params filter/modify retrieval
4Use @PathVariable("name") when parameter name differs from URL template
5Validate path variables with @Positive, @NotNull, etc.

🎯 Practice this topic in interviews

↗ Where this topic fits

Sources

Sources / References

Use these Spring Boot references to verify the concept in official docs and continue into the most relevant SplashRide pages.

Related SplashRide pages

SplashRide Spring Boot learning path

Browse the full Spring Boot topic collection and learning order on SplashRide.

Spring Boot Interview Prep

Practice Spring Boot interview questions and scenario-based answers.

Backend Engineer Career Path

A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.

Full Stack Java Developer Career Path

A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.

Controllers

Master Spring MVC Controllers — the web layer that handles HTTP requests, maps URLs to methods, and returns responses in enterprise REST APIs.

Request Mapping

Master Spring MVC request mapping - how to map HTTP requests to controller methods using @RequestMapping, @GetMapping, @PostMapping, and the full range of mapping options.