RESTFul Web Services CRUD
This post hasn't been updated for 3 years
Trong bài này tôi xin giới thiệu cũng như demo Restful WebService sủ dụng MVC 4,và viết một REST Client với restTemplate để sử dụng những service này . Giới thiệu về về REST REST viết tắt của Representational State Transfer đã được chọn sử dụng rộng rãi thay cho Web service dựa trên SOAP và WSDL.Nó là một kiểu kiến trúc thường sử dụng để thiết kế webservice,các webservice nó có thể sử dụng bởi nhiều các loại client khác nhau.Ý tưởng chính là sử dụng HTTP đơn giản để gọi hơn là sử dụng các cơ chế phức tạp như là CORBAR,RPC hoặc là SOAP.Trong thiết kế cơ bản của rest thì resouces được thực thi bằng tập các động từ thông dụng. -Để tạo một resouces: Thì sử dụng HTTP POST -Để lấy một resouces: Thì sử dung HTTP GET -Để update một resouces: Thì sử dụng HTTP PUT -Để xóa một resouces: Thì sử dụng HTTP DELETE nghĩa là khi bạn là một người phát triển REST hoặc client thì bạn nên tuân theo luật phía trên Thường thì REST dựa trên web service trả lại JSON hoặc XML ,mặc dù nó nó có thể trả các kiểu khác.Client có thể chỉ định loại resource họ muốn,và server sẽ trả lại resource đó bằng cách chỉ rõ Content-Type của resource . Dưới đây là một cách để implement REST API Đây là những gì REST API của chúng ta thực hiện GET request to /api/user/ Trả lại danh sách các user GET request to /api/user/1 Trả lại user với ID 1 POST request to /api/user/ Tạo mới một user PUT request to /api/user/3 Cập nhật user với id=3 DELETE request to /api/user/4 Xóa user có ID 4 DELETE request to /api/user/ Xóa toàn bộ user Chi tiết Chúng ta sử dụng Spring 4 với một anotation mới là @RestController.Ta có thể coi @RestController là sự kết hợp của @Controller và @ResponseBody. Nếu paramter của một phương thức được đánh dấu với @RequestBody,spring sẽ bind các tham số của HTTP request tới các parameter đó,Spring sẽ sử dụng HTTP message converters để convert request body tới domain object,dựa vào ACCEPT or Content-Type trong header của request Nếu một phương thức được đánh dấu với @ResponseBody,spring sẽ bind gia trị kết quả vào HTTP ressponse,spring sẽ sử dụng HTTP Message converters để convert giá tri về HTTP response ,dựa vào ACCEPT or Content-Type trong header của request ResponseEntity:nó đại diện cho toàn bộ HTTP response.bạn có thể control bất ky bên trong nó.bạn có thể chỉ rõ status code,header, và body.nó xuất hiện với một vài hàm khởi tạo mang thông tin bạn muốn gửi trong HTTP Response @PathVariable phương thức này chỉ ra là các tham số của phương thức này được đặt trong url template vaiable {} Basically, @RestController , @RequestBody, ResponseEntity & @PathVariable là tất cả những gì bạn cần biết để implement a REST API in Spring 4. Additionally, spring provides several support classes to help you implement something customized. spring cung cấp một vài class giúp bạn impliment được tùy chỉnh Code triển khai với maven khai báo file pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.websystique.springmvc</groupId> <artifactId>Spring4MVCCRUDRestService</artifactId>
war
<version>1.0.0</version> <name>Spring4MVCCRUDRestService Maven Webapp</name><properties>
<springframework.version>4.2.0.RELEASE</springframework.version>
<jackson.version>2.5.3</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
<warName>Spring4MVCCRUDRestService</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<finalName>Spring4MVCCRUDRestService</finalName>
</build>
</project>
@RestController public class HelloWorldRestController {
@Autowired
UserService userService; //Service which will do all data retrieval/manipulation work
//-------------------Retrieve All Users--------------------------------------------------------
@RequestMapping(value = "/user/", method = RequestMethod.GET)
public ResponseEntity<List<User>> listAllUsers() {
List<User> users = userService.findAllUsers();
if(users.isEmpty()){
return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND
}
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
//-------------------Retrieve Single User--------------------------------------------------------
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> getUser(@PathVariable("id") long id) {
System.out.println("Fetching User with id " + id);
User user = userService.findById(id);
if (user == null) {
System.out.println("User with id " + id + " not found");
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<User>(user, HttpStatus.OK);
}
//-------------------Create a User--------------------------------------------------------
@RequestMapping(value = "/user/", method = RequestMethod.POST)
public ResponseEntity<Void> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder) {
System.out.println("Creating User " + user.getName());
if (userService.isUserExist(user)) {
System.out.println("A User with name " + user.getName() + " already exist");
return new ResponseEntity<Void>(HttpStatus.CONFLICT);
}
userService.saveUser(user);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
//------------------- Update a User --------------------------------------------------------
@RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
public ResponseEntity<User> updateUser(@PathVariable("id") long id, @RequestBody User user) {
System.out.println("Updating User " + id);
User currentUser = userService.findById(id);
if (currentUser==null) {
System.out.println("User with id " + id + " not found");
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
currentUser.setName(user.getName());
currentUser.setAge(user.getAge());
currentUser.setSalary(user.getSalary());
userService.updateUser(currentUser);
return new ResponseEntity<User>(currentUser, HttpStatus.OK);
}
//------------------- Delete a User --------------------------------------------------------
@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
public ResponseEntity<User> deleteUser(@PathVariable("id") long id) {
System.out.println("Fetching & Deleting User with id " + id);
User user = userService.findById(id);
if (user == null) {
System.out.println("Unable to delete. User with id " + id + " not found");
return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
}
userService.deleteUserById(id);
return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
}
//------------------- Delete All Users --------------------------------------------------------
@RequestMapping(value = "/user/", method = RequestMethod.DELETE)
public ResponseEntity<User> deleteAllUsers() {
System.out.println("Deleting All Users");
userService.deleteAllUsers();
return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
}
}
Để test api này ta sử dụng một external của chrome là POSTMAN. 1.Lấy toàn bộ user 2.Lấy 1 đối tượng user Bạn có thể băn khoăn làm thế nào mà kết quả trả về được gửi dưới dạng JSON.thực tế là chứng ta đã included thư viện Jackson trong project của chúng ta.Spring đã sử dụng MappingJackson2HttpMessageConverter để convert kết quả trả về dưới dạng JSON 3.Tao một đối tượng theo đối tượng post và put thì client gửi dữ liệu tới server và chúng chỉ rõ loại dữ liệu khi gửi 2.Viết rest client sử dung restemplate Postman là một công cụ client tuyệt vời để kiểm tra rest api.nhưng nếu bạn muốn sử dụng REST service từ ứng dụng của bạn,bạn sẽ cần REST phía client cho ứng dụng của bạn .một trong nhưng HTTP phía client là 6 phương thức Apache HTTP Các phương thức HTTP và các phương thức RestTemplate HTTP GET : getForObject, getForEntity HTTP PUT : put(String url, Object request, String…urlVariables) HTTP DELETE : delete HTTP POST : postForLocation(String url, Object request, String… urlVariables), postForObject(String url, Object request, Class responseType, String… uriVariables) HTTP HEAD : headForHeaders(String url, String… urlVariables) HTTP OPTIONS : optionsForAllow(String url, String… urlVariables) HTTP PATCH and others : exchange execute Custom rest client public class SpringRestTestClient {
public static final String REST_SERVICE_URI = "http://localhost:8080/Spring4MVCCRUDRestService";
/* GET */
@SuppressWarnings("unchecked")
private static void listAllUsers(){
System.out.println("Testing listAllUsers API-----------");
RestTemplate restTemplate = new RestTemplate();
List<LinkedHashMap<String, Object>> usersMap = restTemplate.getForObject(REST_SERVICE_URI+"/user/", List.class);
if(usersMap!=null){
for(LinkedHashMap<String, Object> map : usersMap){
System.out.println("User : id="+map.get("id")+", Name="+map.get("name")+", Age="+map.get("age")+", Salary="+map.get("salary"));;
}
}else{
System.out.println("No user exist----------");
}
}
/* GET */
private static void getUser(){
System.out.println("Testing getUser API----------");
RestTemplate restTemplate = new RestTemplate();
User user = restTemplate.getForObject(REST_SERVICE_URI+"/user/1", User.class);
System.out.println(user);
}
/* POST */
private static void createUser() {
System.out.println("Testing create User API----------");
RestTemplate restTemplate = new RestTemplate();
User user = new User(0,"Sarah",51,134);
URI uri = restTemplate.postForLocation(REST_SERVICE_URI+"/user/", user, User.class);
System.out.println("Location : "+uri.toASCIIString());
}
/* PUT */
private static void updateUser() {
System.out.println("Testing update User API----------");
RestTemplate restTemplate = new RestTemplate();
User user = new User(1,"Tomy",33, 70000);
restTemplate.put(REST_SERVICE_URI+"/user/1", user);
System.out.println(user);
}
/* DELETE */
private static void deleteUser() {
System.out.println("Testing delete User API----------");
RestTemplate restTemplate = new RestTemplate();
restTemplate.delete(REST_SERVICE_URI+"/user/3");
}
/* DELETE */
private static void deleteAllUsers() {
System.out.println("Testing all delete Users API----------");
RestTemplate restTemplate = new RestTemplate();
restTemplate.delete(REST_SERVICE_URI+"/user/");
}
public static void main(String args[]){
listAllUsers();
getUser();
createUser();
listAllUsers();
updateUser();
listAllUsers();
deleteUser();
listAllUsers();
deleteAllUsers();
listAllUsers();
}
} Trên đây là một demo nhỏ về cách sử dung restfull web service.Hi vọng sẽ giúp ích cho công việc và học tập của bạn Một số tài liệu tham khảo https://www.ibm.com/developerworks/vn/library/ws-restful/ https://en.wikipedia.org/wiki/Representational_state_transfer http://websystique.com/springmvc/spring-mvc-4-restful-web-services-crud-example-resttemplate/
All Rights Reserved