Annotation @PathVariable là gì ? @PathVariable được sử dụng để lấy giá trị trên URI theo template (còn gọi là URI template). @PathVariable thì nó chỉ có một giá trị thuộc tính cho mẫu URI. Trong một method có thể sử dụng nhiều @PathVariable để đón các dữ liệu khác nhau trên URI.
@PathVariable Mapping cơ bản
Để Mapping hoạt động chính xác, tên của biến URI đã bắt{id} và @PathVariable biến String id phải giống nhau.
{id} -> @PathVariable String id -> OK
{id} -> @PathVariable String name -> Lỗi, id và name khác nhau
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@GetMapping("/api/page/{id}")
public String getPageById(@PathVariable String id) {
return id;
}
curl http://localhost:8080/api/page/1
1
@PathVariable Mapping cơ bản – Different Name
Chúng ta cũng có thể truy cập rõ ràng vào biến URI đã bắt bằng cách gán đối số vào annotation @PathVariable.
{id} -> @PathVariable String id -> OK
{id} -> @PathVariable String name -> Lỗi, id và name khác nhau
{id} -> @PathVariable("id") String name -> ok
@GetMapping("/api/title/{title}")
public String getPageByName(@PathVariable("title") String name) {
return name;
}
curl http://localhost:8080/path/api/title/hello-world
hello-world
@PathVariable Mapping cơ bản – Class and method levels
Ví dụ dưới đây cho thấy cách sử dụng @PathVariable để truy cập các biến URI ở cấp độ class và method.
@RestController
@RequestMapping("/path2/api/{id}")
public class PathVariableController2 {
@GetMapping("/page/{title}")
public String getPageById(@PathVariable String id, @PathVariable String title) {
return id + title;
}
}
curl http://localhost:8080/path2/api/99/page/hello-world/
99hello-world
Multiple Captured URI Variables
Chúng ta có thể xác định nhiều @PathVariable chú thích để truy cập các biến URI đã bắt.
@GetMapping("/api/multi/{tag}/{name}")
public String getPageByTagAndName(@PathVariable String tag, @PathVariable String name) {
return tag + ":" + name;
}
curl http://localhost:8080/path/api/multi/spring-mvc/hello-world
spring-mvc:hello-world
Multiple Captured URI Variables ( Map Version )
Chú thích @PathVariable hỗ trợ java.util.Map kiểu dữ liệu.
@GetMapping("/api/multi/{tag}/and/{name}")
public String getPageByTagAndNameMapVersion(@PathVariable Map<String, String> map) {
String tag = map.get("tag");
String name = map.get("name");
if (tag != null && name != null) {
return tag + ":" + name;
} else {
return "Tag or name are missing";
}
}
curl http://localhost:8080/path/api/multi/spring-mvc/and/hello-world
spring-mvc:hello-world
Regex Mapping in java
@PathVariable hỗ trợ regex {varName:regex} để truy cập các URI đã bắt.
// From docs.spring.io, modify to support version double digits and .RELEASE as optional
// spring-webmvc-5.3.22.jar, spring-webmvc-5.2.22.RELEASE.jar
@GetMapping("/api/get/{name:[a-z-]+}-{version:\\d{1,2}\\.\\d{1,2}\\.\\d{1,2}(?:\\.RELEASE)?}{ext:\\.[a-z]+}")
public String getJarFile(@PathVariable String name,
@PathVariable String version,
@PathVariable String ext) {
return name + "-" + version + ext;
}
curl http://localhost:8080/path/api/get/spring-webmvc-5.3.22.jar
spring-webmvc-5.3.22.jar
curl http://localhost:8080/path/api/get/spring-webmvc-5.2.22.RELEASE.jar
spring-webmvc-5.2.22.RELEASE.jar
Biến @PathVariable được yêu cầu theo mặc định
Phương thức bên dưới @GetMapping xử lý nhiều đường dẫn yêu cầu, nhưng @PathVariable chúng được yêu cầu theo mặc định, có nghĩa là nếu chúng ta truy cập vào đường dẫn yêu cầu /api2/page/, Spring sẽ trả về mã lỗi máy chủ HTTP 500 và cả thông báo lỗi như biến mẫu URI bị thiếu.
@GetMapping(value = {"/api2/page/", "/api2/page/{id}"})
public String getPageByApi2(@PathVariable String id) {
return id;
}
curl http://localhost:8080/path/api2/page/
HTTP 500
Missing URI template variable 'id' for method parameter of type String
SERVLET: dispatcher
curl http://localhost:8080/path/api2/page/1
1
Set @PathVariable as optional
Chúng ta có thể sử dụng @PathVariable(required = false) để làm tùy chọn.
@GetMapping(value = {"/api3/page/", "/api3/page/{id}"})
public String getPageByApi3(@PathVariable(required = false) String id) {
if (id != null) {
return id;
} else {
return "id is required!";
}
}
curl http://localhost:8080/path/api3/page/
id is required!
curl http://localhost:8080/path/api3/page/1
1
java.util.Optional
@PathVariablethích hỗ trợ Java 8 Optional.
@GetMapping(value = {"/api4/page/", "/api4/page/{id}"})
public String getPageByApi4(@PathVariable Optional<String> id) {
if (id.isPresent()) {
return id.get();
} else {
return "id is required!";
}
// or one line
// return id.orElse("id is required!");
}
curl http://localhost:8080/path/api4/page/
id is required!
curl http://localhost:8080/path/api4/page/1
1
Câu hỏi thường gặp
Tại sao giá trị bị cắt bớt sau dấu chấm (.) cuối cùng ?
@GetMapping("/hello/{name}")
public String whereIsDot(@PathVariable("name") String name) {
return name;
}
Theo mặc định, Spring coi giá trị sau dấu chấm hoặc dấu chấm (.) cuối cùng là phần mở rộng tệp và tự động cắt bớt chúng. Chẳng hạn như ở ví dụ trên, nếu chúng ta truy cập vào đường dẫn yêu cầu “/hello/abc.jar” thì Spring sẽ chỉ trả về “abc“; Spring sẽ cắt ngắn hoặc xóa các từ .jar.
Để khắc phục , chúng ta dùng regex {name:.+}.
@GetMapping("/hello/{name:.+}")
public String whereIsDotFixed(@PathVariable("name") String name) {
return name;
}
Chúng ta có thể đặt giá trị mặc định cho @PathVariable không ?
Nếu null hoặc empty , chúng ta chỉ cần trả lại một cái gì đó như mặc định.
java.util.Optional
@GetMapping(value = {"/api/page/", "/api/page/{id}"})
public String getPageByApi4(@PathVariable Optional<String> id) {
// default id is 99
return id.orElse("99");
}
Một cách khác
@GetMapping(value = {"/api/page/", "/api/page/{id}"})
public String getPageByApi3(@PathVariable(required = false) String id) {
if (id != null) {
return id;
} else {
return "99";
}
}
Cảm ơn các bạn đã ghé thăm. Chúc các bạn thành công!