1. Home
  2. Lập Trình
  3. Annotation @PathVariable Trong Spring
Avatar of Nguyễn Tuấn Nguyễn Tuấn 4 năm trước

Annotation @PathVariable Trong Spring

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!

35 lượt xem