@RequestMapping
là một trong những annotation được sử dụng phổ biến nhất trong Spring MVC. Annotation org.springframework.web.bind.annotation.RequestMapping
được dùng để map các request từ web tới các handler classes và/hoặc các handler methods.
@RequestMapping
có thể được áp dụng cả lớp controller lẫn các phương thức (method). Hôm nay, chúng ta sẽ cùng tìm hiểu nhiều cách sử dụng khác nhau của annotation này thông qua ví dụ, cũng như kết hợp với các annotation khác như @PathVariable
và @RequestParam
.
Spring @RequestMapping
@RequestMapping
với Class:
Chúng ta có thể sử dụng @RequestMapping
tại phần định nghĩa lớp để tạo ra một base URI. Ví dụ:
@Controller
@RequestMapping("/home")
public class HomeController {
}
Now /home
chính là URI mà controller này sẽ xử lý. Khái niệm này khá giống với servlet context trong một ứng dụng web.
@RequestMapping
với Method:
Chúng ta có thể sử dụng @RequestMapping
tại cấp phương thức để chỉ định mẫu URI mà handler method sẽ đảm nhận. Ví dụ:
@RequestMapping(value="/method0")
@ResponseBody
public String method0(){
return "method0";
}
Annotation ở trên cũng có thể được viết dưới dạng @RequestMapping("/method0")
. Nhân tiện, tôi đang sử dụng @ResponseBody
để trả về phản hồi dạng chuỗi cho web yêu cầu này, điều này giúp ví dụ đơn giản và dễ hiểu hơn. Như thường lệ, tôi sẽ sử dụng các phương thức này trong một ứng dụng Spring MVC và kiểm thử bằng một chương trình hoặc script đơn giản.
@RequestMapping
với nhiều URI:
Chúng ta có thể dùng một phương thức duy nhất để xử lý nhiều URI khác nhau. Ví dụ:
@RequestMapping(value={"/method1","/method1/second"})
@ResponseBody
public String method1(){
return "method1";
}
Nếu bạn xem phần mã nguồn của annotation @RequestMapping
, bạn sẽ thấy rằng tất cả các biến của nó đều là mảng. Điều này cho phép chúng ta khai báo một mảng các chuỗi để map nhiều URI khác nhau cho cùng một phương thức xử lý (handler method).
@RequestMapping
với HTTP Method:
Đôi khi, chúng ta muốn thực hiện các hành động khác nhau tùy vào phương thức HTTP được sử dụng, dù URI của request là giống nhau. Trong trường hợp này, chúng ta có thể dùng thuộc tính method
của @RequestMapping
để giới hạn những phương thức HTTP mà một handler method sẽ xử lý. Ví dụ:
@RequestMapping(value="/method2", method=RequestMethod.POST)
@ResponseBody
public String method2(){
return "method2";
}
@RequestMapping(value="/method3", method={RequestMethod.POST,RequestMethod.GET})
@ResponseBody
public String method3(){
return "method3";
}
- @RequestMapping với Headers:
Chúng ta có thể chỉ định các HTTP header bắt buộc phải có trong request để handler method được gọi. Ví dụ:
@RequestMapping(value="/method4", headers="name=pankaj")
@ResponseBody
public String method4(){
return "method4";
}
@RequestMapping(value="/method5", headers={"name=pankaj", "id=1"})
@ResponseBody
public String method5(){
return "method5";
}
- @RequestMapping với
produces
vàconsumes
:
Chúng ta có thể sử dụng các header Content-Type
và Accept
để xác định nội dung của request và kiểu MIME mà client mong muốn nhận trong response. Để đơn giản và rõ ràng hơn, annotation @RequestMapping
cung cấp hai thuộc tính produces
và consumes
, cho phép chúng ta chỉ định kiểu nội dung của request mà phương thức sẽ xử lý, cũng như kiểu nội dung sẽ được trả về trong response. Ví dụ:
@RequestMapping(value="/method6", produces={"application/json","application/xml"}, consumes="text/html")
@ResponseBody
public String method6(){
return "method6";
}
Phương thức ở trên chỉ có thể xử lý các yêu cầu có Content-Type
là text/html
và có khả năng trả về response với định dạng application/json
hoặc application/xml
.
Spring @PathVariable
@RequestMapping
kết hợp với@PathVariable
:
Annotation @RequestMapping
có thể được sử dụng để xử lý các URI động, trong đó một hoặc nhiều phần của URI đóng vai trò là tham số. Chúng ta thậm chí có thể sử dụng biểu thức chính quy để giới hạn kiểu dữ liệu đầu vào cho các tham số động này. Cách này hoạt động cùng với annotation @PathVariable
, cho phép ánh xạ giá trị trong URI vào một tham số cụ thể trong phương thức. Ví dụ:
@RequestMapping(value="/method7/{id}")
@ResponseBody
public String method7(@PathVariable("id") int id){
return "method7 with id="+id;
}
@RequestMapping(value="/method8/{id:[\\\\d]+}/{name}")
@ResponseBody
public String method8(@PathVariable("id") long id, @PathVariable("name") String name){
return "method8 with id= "+id+" and name="+name;
}
Spring @RequestParam
@RequestMapping
kết hợp với@RequestParam
để xử lý các tham số trong URL:
Đôi khi, chúng ta nhận được các tham số từ URL trong request, chủ yếu là trong các request dạng GET.
Chúng ta có thể sử dụng @RequestMapping
kết hợp với annotation @RequestParam
để lấy giá trị tham số từ URL và ánh xạ nó vào tham số đầu vào của phương thức. Ví dụ:
@RequestMapping(value=”/method9″) @ResponseBody public String method9(@RequestParam(“id”) int id){ return “method9 with id= “+id; }
For this method to work, the parameter name should be "id" and it should be of type int.
- Phương thức mặc định(default) với @RequestMapping:
Nếu thuộc tính value
của annotation @RequestMapping
để trống ở một phương thức, thì phương thức đó sẽ được coi là phương thức mặc định của lớp controller nghĩa là nó sẽ xử lý các request đến URI gốc được định nghĩa ở cấp lớp. Ví dụ:
@RequestMapping() @ResponseBody public String defaultMethod(){ return “default method”; }
As you have seen above that we have mapped `/home` to `HomeController`, this method will be used for the default URI requests.
- Phương thức dự phòng (fallback) với @RequestMapping:
Chúng ta có thể tạo một phương thức dự phòng cho lớp controller nhằm đảm bảo rằng tất cả các request từ client đều được xử lý, ngay cả khi không có phương thức nào khớp với yêu cầu đó. Điều này rất hữu ích khi muốn gửi trang phản hồi 404 tùy chỉnh đến người dùng trong trường hợp không tìm thấy phương thức xử lý tương ứng với request.
@RequestMapping(“*”) @ResponseBody public String fallbackMethod(){ return “fallback method”; }
Chương trình kiểm thử Spring RestMapping
Chúng ta có thể sử dụng Spring RestTemplate để kiểm thử các phương thức ở trên, nhưng trong ví dụ hôm nay, tôi sẽ dùng các lệnh cURL để kiểm tra vì chúng đơn giản và lượng dữ liệu truyền không nhiều. Tôi đã tạo một shell script đơn giản tên là springTest.sh để gọi tất cả các phương thức và in ra kết quả của chúng. Nội dung script trông như sau:
#!/bin/bash
echo "curl <https://localhost:9090/SpringRequestMappingExample/home/method0>";
curl <https://localhost:9090/SpringRequestMappingExample/home/method0>;
printf "\\n\\n*****\\n\\n";
echo "curl <https://localhost:9090/SpringRequestMappingExample/home>";
curl <https://localhost:9090/SpringRequestMappingExample/home>;
printf "\\n\\n*****\\n\\n";
echo "curl <https://localhost:9090/SpringRequestMappingExample/home/xyz>";
curl <https://localhost:9090/SpringRequestMappingExample/home/xyz>;
printf "\\n\\n*****\\n\\n";
echo "curl <https://localhost:9090/SpringRequestMappingExample/home/method1>";
curl <https://localhost:9090/SpringRequestMappingExample/home/method1>;
printf "\\n\\n*****\\n\\n";
echo "curl <https://localhost:9090/SpringRequestMappingExample/home/method1/second>";
curl <https://localhost:9090/SpringRequestMappingExample/home/method1/second>;
printf "\\n\\n*****\\n\\n";
echo "curl -X POST <https://localhost:9090/SpringRequestMappingExample/home/method2>";
curl -X POST <https://localhost:9090/SpringRequestMappingExample/home/method2>;
printf "\\n\\n*****\\n\\n";
echo "curl -X POST <https://localhost:9090/SpringRequestMappingExample/home/method3>";
curl -X POST <https://localhost:9090/SpringRequestMappingExample/home/method3>;
printf "\\n\\n*****\\n\\n";
echo "curl -X GET <https://localhost:9090/SpringRequestMappingExample/home/method3>";
curl -X GET <https://localhost:9090/SpringRequestMappingExample/home/method3>;
printf "\\n\\n*****\\n\\n";
echo "curl -H "name:pankaj" <https://localhost:9090/SpringRequestMappingExample/home/method4>";
curl -H "name:pankaj" <https://localhost:9090/SpringRequestMappingExample/home/method4>;
printf "\\n\\n*****\\n\\n";
echo "curl -H "name:pankaj" -H "id:1" <https://localhost:9090/SpringRequestMappingExample/home/method5>";
curl -H "name:pankaj" -H "id:1" <https://localhost:9090/SpringRequestMappingExample/home/method5>;
printf "\\n\\n*****\\n\\n";
echo "curl -H "Content-Type:text/html" <https://localhost:9090/SpringRequestMappingExample/home/method6>";
curl -H "Content-Type:text/html" <https://localhost:9090/SpringRequestMappingExample/home/method6>;
printf "\\n\\n*****\\n\\n";
echo "curl <https://localhost:9090/SpringRequestMappingExample/home/method6>";
curl <https://localhost:9090/SpringRequestMappingExample/home/method6>;
printf "\\n\\n*****\\n\\n";
echo "curl -H "Content-Type:text/html" -H "Accept:application/json" -i <https://localhost:9090/SpringRequestMappingExample/home/method6>";
curl -H "Content-Type:text/html" -H "Accept:application/json" -i <https://localhost:9090/SpringRequestMappingExample/home/method6>;
printf "\\n\\n*****\\n\\n";
echo "curl -H "Content-Type:text/html" -H "Accept:application/xml" -i <https://localhost:9090/SpringRequestMappingExample/home/method6>";
curl -H "Content-Type:text/html" -H "Accept:application/xml" -i <https://localhost:9090/SpringRequestMappingExample/home/method6>;
printf "\\n\\n*****\\n\\n";
echo "curl <https://localhost:9090/SpringRequestMappingExample/home/method7/1>";
curl <https://localhost:9090/SpringRequestMappingExample/home/method7/1>;
printf "\\n\\n*****\\n\\n";
echo "curl <https://localhost:9090/SpringRequestMappingExample/home/method8/10/Lisa>";
curl <https://localhost:9090/SpringRequestMappingExample/home/method8/10/Lisa>;
printf "\\n\\n*****\\n\\n";
echo "curl <https://localhost:9090/SpringRequestMappingExample/home/method9?id=20>";
curl <https://localhost:9090/SpringRequestMappingExample/home/method9?id=20>;
printf "\\n\\n*****DONE*****\\n\\n";
Lưu ý rằng tôi đã triển khai ứng dụng web của mình trên Tomcat 7, và ứng dụng đang chạy tại cổng 9090. SpringRequestMappingExample
là servlet context của ứng dụng.
Bây giờ, khi tôi chạy script này thông qua dòng lệnh command line, tôi nhận được kết quả đầu ra như sau:
pankaj:~ pankaj$ ./springTest.sh
curl <https://localhost:9090/SpringRequestMappingExample/home/method0>
method0
*****
curl <https://localhost:9090/SpringRequestMappingExample/home>
default method
*****
curl <https://localhost:9090/SpringRequestMappingExample/home/xyz>
fallback method
*****
curl <https://localhost:9090/SpringRequestMappingExample/home/method1>
method1
*****
curl <https://localhost:9090/SpringRequestMappingExample/home/method1/second>
method1
*****
curl -X POST <https://localhost:9090/SpringRequestMappingExample/home/method2>
method2
*****
curl -X POST <https://localhost:9090/SpringRequestMappingExample/home/method3>
method3
*****
curl -X GET <https://localhost:9090/SpringRequestMappingExample/home/method3>
method3
*****
curl -H name:pankaj <https://localhost:9090/SpringRequestMappingExample/home/method4>
method4
*****
curl -H name:pankaj -H id:1 <https://localhost:9090/SpringRequestMappingExample/home/method5>
method5
*****
curl -H Content-Type:text/html <https://localhost:9090/SpringRequestMappingExample/home/method6>
method6
*****
curl <https://localhost:9090/SpringRequestMappingExample/home/method6>
fallback method
*****
curl -H Content-Type:text/html -H Accept:application/json -i <https://localhost:9090/SpringRequestMappingExample/home/method6>
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json
Content-Length: 7
Date: Thu, 03 Jul 2014 18:14:10 GMT
method6
*****
curl -H Content-Type:text/html -H Accept:application/xml -i <https://localhost:9090/SpringRequestMappingExample/home/method6>
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/xml
Content-Length: 7
Date: Thu, 03 Jul 2014 18:14:10 GMT
method6
*****
curl <https://localhost:9090/SpringRequestMappingExample/home/method7/1>
method7 with id=1
*****
curl <https://localhost:9090/SpringRequestMappingExample/home/method8/10/Lisa>
method8 with id= 10 and name=Lisa
*****
curl <https://localhost:9090/SpringRequestMappingExample/home/method9?id=20>
method9 with id= 20
*****DONE*****
pankaj:~ pankaj$
Hầu hết các phần trên đều khá dễ hiểu, tuy nhiên bạn có thể muốn kiểm tra kỹ hơn phương thức mặc định và phương thức dự phòng để nắm rõ cách hoạt động của chúng.
Đó là tất cả nội dung về ví dụ Spring @RequestMapping. Hy vọng bài viết này sẽ giúp bạn hiểu rõ hơn về annotation này cùng với các tính năng khác nhau của nó.