REST
REST (REpresentational State Transfer)
2021/11/28 (增加連結)
基本概念
REST (REpresentational State Transfer)是提供web services的一種方法,REST利用HTTP的POST,GET , PUT, DELETE來進行CRUD。
True RESTful API : REST Architectural Constraints
Stateless
Client-Server
Uniform Interface
Cacheable
Layered system
Code on demand
11 things you should know about GET vs POST
GET parameters will be stored on browser’s session history.
GET responses can be cached
Get is a safe method
Static Websites only responds to GET requests
Which method has length restrictions? GET
Which method is more secure and should be used to deal with sensitive data? POST
Which method can be bookmarked? GET
一般而言,我們是利用RESTful web services,與其他的web site或手機交換資料。所以,下面的範例可以想像成去另外一個網站(雖然目前的url是localhost)取得資料。
http://localhost:8080/customer/1 的內容類似:
{
"name" : "Ben",
"address" : "新北市新莊區中正路510號",
"weight" : 60,
"_links" : {
"self" : {
"href" : "http://localhost:8080/customer/1"
},
"customer" : {
"href" : "http://localhost:8080/customer/1"
}
}
}
http://localhost:8080/customer 的內容類似:
{
"_embedded" : {
"customer" : [ {
"name" : "Ben",
"address" : "新北市新莊區中正路510號",
"weight" : 60,
"_links" : {
"self" : {
"href" : "http://localhost:8080/customer/1"
},
"customer" : {
"href" : "http://localhost:8080/customer/1"
}
}
}, {
"name" : "Cathy",
"address" : "台北市仁愛路1號",
"weight" : 65,
"_links" : {
"self" : {
"href" : "http://localhost:8080/customer/2"
},
"customer" : {
"href" : "http://localhost:8080/customer/2"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/customer{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://localhost:8080/profile/customer"
}
},
"page" : {
"size" : 20,
"totalElements" : 2,
"totalPages" : 1,
"number" : 0
}
}
Spring REST
基本上,在Spring 4裡,加上了@RestController就可以! (詳參: Spring MVC @RestController與@Controller的區別)
package com.example.demo;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.SpringApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmployeeController {
private List<Employee> employeeList = new ArrayList<>();
private int count=0;
public EmployeeController(){
employeeList.add(new Employee(1, "Arpit", "IT"));
employeeList.add(new Employee(2, "Sanjeev", "IT"));
employeeList.add(new Employee(3, "Ben", "IT"));
count = 3;
}
@GetMapping("/employee/get")
public List<Employee> get() {
return employeeList;
}
@PostMapping("/employee/")
public void post(@RequestBody Employee employee) {
count++;
employee.setId(count);
employeeList.add(employee);
}
}
輸入
http://localhost:8080/employee/get
會得到
[{"id":1,"name":"Arpit","department":"IT"},{"id":2,"name":"Sanjeev","department":"IT"},{"id":3,"name":"Ben","department":"IT"}]
Data REST
除了RestController,Spring還提供Spring Data Rest,基本上Spring Data Rest是將Rest架在Spring JPA上,也就是當資料的存取設定好了之後,REST服務就好了,提供REST服務,可以讓App (不管是Android或iOS)都可以新增、取得、更新及刪除資料,詳參: Spring REST (Spring Data Rest) 。
客製搜尋
If you have query methods defined, those also default to be exposed by their name:
interface PersonRepository extends CrudRepository<Person, Long> {
List<Person> findByName(String name);
}
This would be exposed under the URL: http://localhost:8080/persons/search/findByName
All query method resources are exposed under the resource search.
To change the segment of the URL under which this query method is exposed, use the @RestResource annotation again:
@RepositoryRestResource(path = "people")
interface PersonRepository extends CrudRepository<Person, Long> {
@RestResource(path = "names")
List<Person> findByName(String name);
}
Now this query method will be exposed under the URL: http://localhost:8080/people/search/names
詳參: https://docs.spring.io/spring-data/rest/docs/current/reference/html/
參考資料
REST
https://en.wikipedia.org/wiki/Representational_state_transfer
API Architecture — Design Best Practices for REST APIs
Learn the basics of HTTP
Do not return plain text
most REST APIs by convention use JSON as the data format
Do not use verbs in URIs
Use plural nouns for resources
Return the error details in the response body
Pay special attention to HTTP status codes
You should use HTTP status codes consistently
Do not nest resources
Handle trailing slashes gracefully
Make use of the querystring for filtering and pagination
Know the difference between 401 Unauthorized and 403 Forbidden
Make good use of HTTP 202 Accepted
Use a web framework specialized in REST APIs
API Architecture — Performance Best Practices for REST APIs
Reduce and limit the Payload Size
Enable caching
Provide sufficient Network speed
Prevent accidental calls, slowdowns, and abuse
Try to use PATCH over PUT
Enable Logging, Monitoring, and Alerting
Enable Pagination
How not to blow your REST interview
The 5 principles of REST
Contract first approach / Uniform Resource identifiers
Statelessness
Client-Server model
Caching
Layered architecture
Spring
使用Spring Data Rest
Spring Rest:Jackson’s JsonNode for Payload unaware request Handling
7 Reasons I Do Not Use JAX-RS in Spring Boot Web Applications
Spring MVC Results in More "Standard" Applications (Ironically)
I Don't Have to Think as Much About Versions
I Don't Have to Think About Multiple IoC Containers
I Don't Have to Register JAX-RS Resource Classes
I Feel Less Guilty About Being Non-RESTful
Actuator Just Works
I Can Use MockMvc
JAX-RS
spring rest 容易被忽視的後端服務 chunked 效能問題
這樣就解決了 sprng mvc 和 jersey rest 共同存在的問題,我們也不需要將所有的返回 chunked 的介面都改成 JAX-RS 的 rest 服務,只需要將有效能瓶頸的介面改造下即可。
Jersey
RestEasy