同JDBCTemplate一样,为了消除大量繁琐的样板代码,RestTemplate提供了很多方法,使得我们能够很方便的调用REST服务。这些方法大致可分为以下12组重载方法:
Method group | Description |
---|---|
|
Retrieves a representation via GET. |
|
Retrieves a |
|
Retrieves all headers for a resource by using HEAD. |
|
Creates a new resource by using POST and returns the |
|
Creates a new resource by using POST and returns the representation from the response. |
|
Creates a new resource by using POST and returns the representation from the response. |
|
Creates or updates a resource by using PUT. |
|
Updates a resource by using PATCH and returns the representation from the response. Note that the JDK |
|
Deletes the resources at the specified URI by using DELETE. |
|
Retrieves allowed HTTP methods for a resource by using ALLOW. |
|
More generalized (and less opinionated) version of the preceding methods that provides extra flexibility when needed. It accepts a These methods allow the use of |
|
The most generalized way to perform a request, with full control over request preparation and response extraction through callback interfaces. |
RestTemplate API
要使用RestTmeplate
,我们应该创建它的一个实例,或者是注入该类的bean。
public Ingredient getIngredientById(String ingredientId){
return rest.getForObject("http://localhost:8080/api/ingredients/{id}",Ingredient.class,ingredientId);
}
第一个参数指定接口接口的URL,第二个参数指定返回值绑定的类型,第三个参数被绑定到URL中的{id}
占位符。
URL参数我们也可以存放在Map中:
public Ingredient getIngredientById(String ingredientId){
Map<String,Object> params = new HashMap<>();
params.put("id",ingredientId);
return rest.getForObject("http://localhost:8080/api/ingredients/{id}",Ingredient.class,params);
}
URL中的“{id}”占位符被params中key为“id”的值所替换。
使用URI
参数相对来说要复杂一点:
public Ingredient getIngredientById(String ingredientId){
Map<String,Object> params = new HashMap<>();
params.put("id",ingredientId);
URI url = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/api/tacos/{id}").build(params);
return rest.getForObject(url,Ingredient.class);
}
我们还可以使用getForEntity
方法,该方法返回ResponseBody
,包含了出domain对象之外更多的信息。
我们使用RestTemplate.put()
来替换资源。与getForObject
或getForEntity
用法几乎一样,只是该方法的第二个参数是替换的实体对象,如:
public Taco put(){
Taoc taco = new Taco();
taco.setName("tacoOne");
...
restTemplate.put("http://localhost:8080/rest/design/{id}",taco,12);//将id为12的记录替换为taco
return taco;
}
public void delete(String id){
restTemplate.delete("http://localhost:8080/rest/design/",id);
}
delete
方法只需要两个入参:URL和URL参数。
如果我们想要得到创建之后的对象,我们可以使用:postForObject
:
public Taco create(Taco){
return taco = restTemplate.postForObject("http://localhost:8080/rest/design",taco,Taco.class);
}
第二个参数为新增资源对象,第三个参数指定响应体的绑定的类型。
如果我们想要得到新增资源的地址,我们可以使用postForLocation
public URI create(Taco taco){
return restTemplate.postForLocation("http://localhost:8080/rest/design",taco);
}
返回的URI源于响应体的Location Header。
如果两者都想要则使用postForEntity
:
public Taco create(Taco taco){
ResponseEntity<Taco> entity = restTemplate.postForEntity("http://localhost:8080/rest/design",taco,Taco.class);
URI uri = entity.getHeader().getLocation();
return entity.getBody();
}
上面的例子使用的资源全都不含有超链接,若我们所使用的API返回的资源中含有链接,那么RestTemplate就发挥不了作用了。
Tranverson同Spring Data HATEOAS协同工作,是使用Spring应用中hypermedia API的解决方案。
首先同RestTemplate
一样,我们首选需要一个Tranverson
实例,可以实例化一个或者注入Tranverson
bean;
Tranverson tranverson = new Tranverson(URI.create("http://localhost:8080/api"),MediaTypes.HAL_JSON);
实例化一个Traverson
对象,并指定Spring Data REST API的根路径为起始路径;同时指定我们使用的接口将返回JSON格式的数据,数据包含HAL风格的链接,这样Traverson才能正确解析响应结果。
所以我们可以使用与链接对应的关系名称来访问接口:
tranverson.follow("ingredients");//请求http://localhost:8080/api/ingredients
tranverson.follow("tacos","recent");//请求http://localhost:8080/api/tacos/recent
ParameterizedTypeReference<CollectionModel<Taco>> tacos = new ParameterizedTypeReference<CollectionModel<Taco>>() {};
CollectionModel<Taco> tacos = traverson.follow("tacos").toObject(tacos);
toObject
方法的入参类型为ParameterizedTypeReference
,表示Traverson将会读入CollectionModel
类型的数据。
因为Traverson发起的所有请求都是HTTP GET类型的,所以我们无法使用Traverson来新增、更新和删除资源。因此,一般情况下我们可能会结合Traverson和RestTemplate一起使用。
String ingredientsUrl = traverson.follow("ingredients").asLink().getHref();
restTemplate.postForObject(ingredientsUrl,ingredient,Ingredient.class);
asLink
将会返回资源本身的链接(_links下的self)