网站设计书,找个网站看看,开发公司年度工作总结,郑州官方网目录 概述GET资源PUT资源DELETE资源POST资源 概述
Spring应用除了提供对外API之外#xff0c;同时要对另一个应用的API发起请求。实际上#xff0c;在微服务领域#xff0c;这正变得越来越普遍。因此#xff0c;花点时间研究一下如何使用Spring与RESTAPI交互是非常值得的。… 目录 概述GET资源PUT资源DELETE资源POST资源 概述
Spring应用除了提供对外API之外同时要对另一个应用的API发起请求。实际上在微服务领域这正变得越来越普遍。因此花点时间研究一下如何使用Spring与RESTAPI交互是非常值得的。 Spring应用可以采用多种方式来消费RESTAPI。
RestTemplatc:由Spring核心框架提供的简单、同步REST客户端。Traverson:对 Spring RestTemplate 的包装由Spring HATEOAS 提供的支持超链接、同步的 REST客户端其灵感来源于同名的 JavaScript库。WebClient:反应式、异步REST的客户端。
现在我们主要关注使用 RestTemplate 创建客户端。 从客户端的角度来看与 REST 资源进行交互涉及很多工作而且大多数都是很单调乏味的样板式代码。如果使用较低层级HTTP 库客户端需要创建一个客户端实例和请求对象执行请求解析响应将响应映射为领域对象还要处理这个过程中可能会抛出的所有异常。不管发送什么样的 HTTP 请求这种样板代码都要不断重复。 为了避免这种样板代码Spring 提供了 RestTemplate。就像JDBCTemplate 能够处理JDBC 中丑陋的那部分代码一样RestTemplate 也能够将你从消费 REST 资源所面临的单调工作中解放出来。 RestTemplat 提供了 41个与 REST 资源交互的方法。我不会介绍它所提供的所有方法而是只考虑独立的12个操作这些操作的重载形式组成了完整的41个方法。
方法描述delete(…)在特定的URL上对资源执行HTTP DELETE请求exchange(…)在URL上执行特定的 HTTP 方法返回包含对象的 ResponseEntity个对象是从响应体中映射得到的execute(…)在URL上执行特定的 HTTP方法返回一个从响应体映射得到的对象getForEntity(…)发送一个HTTP GET 请求返回的ResponseEntity 包含了响应体所映射成的对象getForObject(…)发送一个HTTP GET 请求返回响应体所映射成的对象headForHeaders(…)发送HTTP HEAD 请求返回包含特定资源 URL 的 HTTP头信息optionsForAllow(…)发送HTTP OPTIONS 请求返回特定 URL的Allow头信息patchForObject(…)发送HTTP PATCH请求返回一个从响应体映射得到的对象postForEntity(…POST数据到一个URL返回包含一个对象的 ResponseEntity,这个对象是从响应体中映射得到的postForLocation(…)POST数据到一个URL返回新创建资源的URLpostForObject(…POST数据到一个URL返回根据响应体映射形成的对象put(…)PUT资源到特定的URL
除了 TRACE,RestTemplate 对每种标准的HTTP 方法都提供了至少一个方法。除之外execute()和exchange()提供了较低层次的通用方法以便使用任意的HTTP 操作 表中的大多数操作都以如下的3种方法形式进行了重载:
使用String作为URL格式并使用可变参数列表指明 URL 参数;使用String作为URL格式并使用MapString,String指明 URL参数;使用java.net.URI作为URL格式不支持参数化URL。
明确了 RestTemplate 所提供的 12 个操作以及各个变种如何工作之后我们就能以自己的方式编写消费 REST资源的客户端了。 要使用 RestTemplate可以在需要的地方创建一个实例:
RestTemplate rest new RestTemplate();也可以将其声明为一个 bean 并注入到需要的地方:
Bean
public RestTemplate restTemplate() {return new RestTemplate();
}我们从其支持的4个主要 HTTP 方法(也就是GET、PUT、DELETE和POST)入手来研究 RestTemplate 的操作。不妨从 GET方法的 getForObject()和 getForEntity()开始。
GET资源
假设我们现在想要通过 Taco Cloud API访问该RestAPI可以得到对应的数据获取某个配料。为了实现这一点我们可以使用RestTemplate的getForObject()方法来获取配料。例如如下的代码使用RestTemplate来根据ID来获Ingredient 对象:
public Ingredient getIngredientById(string ingredientId){return rest.getForObject(http://localhost;8080/ingredients/{id},Ingredient.class, ingredientId);
}在这里我们使用了gctForObject()的变种形式它接收一个String 类型的URL并使用可变列表来指定URL变量。传递给getForObject()的 IngredientId 参数会用来填充给定URL的{id}占位符。尽管在本例中只有一个URL 变量但是有很重要的一点需要我们注意:变量参数会按照它们出现的顺序被设置到占位符中。 getForObject()方法的第二个参数是响应应该绑定的类型。在本例中响应数据(很可能是JSON格式)应该被反序列化为要返回的Igredient对象。另外一种替代方案是使用Map 来指定URL变量:
public Ingredient getIngredientById(String ingredientId) (MapString,String urlVariables new HashMap();urlVariables.put(id, ingredientId);return rest.getForObject(http://localhost:8080/ingredients/{id},Ingredient.class, urlVariables);在本例中ingredicntId 的值会映射到名为 id 的 key 上。当发起请求的时候{id}占位符将会被替换成key为id的Map条目。 使用 URI参数要稍微复杂一些这种方式需要我们在调用 getForObject()之前构建URI对象。在其他方面它与另外两个变种非常类似:
public Ingred1ent getIngredientById(String ingredientId) {MapString,String urlVariables new HashMap();urlVariables.put(id, ingredientId);URI urlUriComponentsBuilder.fromHttpUrl(http://localhost:8080/ingredients/{id}).build(urlVariables);return rest,getForObject(url, Ingredient.class);
}在这里URI对象是通过 String 规范定义的它的占位符会被 Map 中的条目替换。这与我们之前看到的 getForObject()变种非常相似。getForObject()是获取资源的有效式。但是如果客户端需要的不仅仅是载荷体那么可以考虑使用 getForEntity()。getForEntity()的工作方式和 getForObject()类似但是它所返回的并不是代表响应载荷的领域对象而是会包裹领域对象的 ResponseEntity 对象。借助 ResponseEntity 对象能够访问很多响应细节比如响应头信息。 例如假设我们除了想要获取配料数据还想要从响应中探查 Date 头信息。借助getForEntity()这个需求能够很容易实现:
public Ingredient getIngredientById(String ingredientId) {
ResponseEntityIngredient responseEntity rest.getForEntity(http://localhost:8080/ingredients/{id},Ingredient.class ingredientId);
log.info(Fetched time: {},
responseEntity.getHeaders().getDate());
return responseEntity.getBody();
}getForEntity()有着与 getForObject()方法相同参数的重载形式所以我们可以按照变列表参数的形式提供 URL变量也可以按照 URI对象的形式调用 getForEntity()。
PUT资源
为了发送HTTP PUT 请求RestTemplate 提供了 put()方法。put()方法的3个变种形式都会接收一个会被序列化并发送至给定 URL的 Object。就URL本身来讲它可以按照URI对象或 String 的形式来指定。与 getForObject()和 getForEntity()类似URL变量能够以可变参数列表或Map的形式提供。 假设我们想要使用一个新 Igredient 对象的数据来替换某个配料资源那么如下的代码片段就能做到这一点:
public void updateIngredient(Ingredient ingredient) {rest.put(http://localhost:8080/ingredients/{id},ingredientingredient.getId());
}在这里URL 是以 String 的形式指定的该 URL 包含一个占位符它会被给定Ingredient 的id 属性所替换。要发送的数据是 Ingredient 对象本身。put()方法返回 void 所以我们没有必要处理返回值。
DELETE资源
假设 Taco Cloud 不想再提供某种配料因此我们要从可选列表中将其完全删除。为了实现这一点可以使用 RestTemplate 来调用 delete() 方法:
public void deleteIngredlent(Ingredient ingredient) {rest.delete(http://1ocalhost;8080/ingredients/{id}),ingredient.getId())
}在本例中我们只为 delete()提供了 URL以 String 的形式指定)和 URL变量值但是和其他的 RestTemplate 方法类似URL 能够以URI对象的方式来指定URL参数也能够以 Map 的方式来声明。
POST资源
现在我们假设要添加新的配料到 Taco Cloud 菜单中。为了实现这一点我“.../ingredients”端点发送 HTTP POST 请求并将配料数据放到请求体中。RestTemplate 有 3种发送 POST 请求的方每种方法都有相同的重载变种来指定URL。如果希望在 POST请求之后得到新创建的 Ingredient 资源可以按照如下的方式使用 postForObject():
public Ingredient createIngredient(Ingredient ingredient) {return rest.postForObject(http://localhost:8080/ingredients,ingredient,Ingredient.class);
}postForObject()方法的这个变种形式接收 String类型的URL规范、要提交给服务器端的对象以及响应体应该绑定的领域类型。尽管我们在这里没有用到但是第 4个参数可以是URL变量值的Map 或可变参数的列表。它们能够替换到 URL之中。如果客户端还想要知道新创建资源的地址那么可以调用 postForLocation()方法如下所示:
public java,net.URI createIngredient(Ingredient ingredient) {return rest.postForLocation(http://localhost:8080/ingredients,ingredient);
}注意postForLocation()有与 postForObject()类似的工作方式只不过它返回的是新创建资源的 URI,而不是资源对象本身。这里返回的 URI是从响应的 Location 头信息中派生出来的。如果同时需要地址和响应载荷可以使用 postForEntity()方法:
public Ingredient createIngredient(Ingredient ingredient) (ResponseEntityIngredient responseEntityrest.postForEntity(http://localhost:8080/ingredients,ingredient,Ingredient.class);log.Info(New resource created at {},responseEntity.getHeaders().getLocation());return responseEntity.getBody();
}尽管 RestTemplate 的方法可以实现不同的目的但是用法非常相似。因此我们很容易就可以精通 RestTemplate并将其用到客户端代码中。