在Spring cloud 框架中,我们都知道,起一个MVC的服务非常简单。 通过controller 注释就可以写一个API的接口了。
但是如果我们的service 想要发起一个新的调用如何做呢?在Spring cloud 下有不少这样的需求。
主要有这么几种方式:
- 通过
restTemplate、webClient等组件来封装HTTP请求。 - 通过
OpenFeign这样的组件类实现微服务之间调用。
背景
简单介绍下背景,RestTemplate 是一个轻量级的HTTP的Client,相对于 Feign 而言。 RestTemplate有丰富的接口,支持用户对HTTP的各种请求方法和参数的封装 。
OpenFeign是有Feign 开发而来。是Spring Cloud 的子项目之一,在微服务调用中,OpenFeign非常的得心应手,而且OpenFeign还支持各种HTTP调用封装,同时还可以整合服务注册(Eureka)、负载均衡、服务治理(熔断、限流、重试)的组件,灵活性提升很多而且实现起来比较简单。
RestTemplate 用法
RestTemplate支持HTTP的 HEAD, GET, POST, PUT, DELETE, OPTIONS、PATCH等大部分方法,还有两个TRACE、CONECT 用的比较少,不支持(查询官方接口确认)。
我们就来总结一下常用的方法的实现。
GET
支持的方法有:
- getForObject(url,classType)通过对URL进行GET方法请求。响应(如果有)被解析到给定的类的类型并返回。
- getForEntity(url,responseType)–通过对URL进行GET方法请求,响应结果以ResponseEntity的形式返回。
- exchange(requestEntity,responseType)– 执行指定的请求,并将响应作为ResponseEntity返回。
- execute(url,httpMethod,requestCallback,responseExtractor)–对给定的URI模板执行httpMethod,使用RequestCallback准备请求,并使用ResponseExtractor读取响应。
来个例子吧。
server 端的API的是这样式的
@RequestMapping(value = "/employees", produces = MediaType.APPLICATION_XML_VALUE, method = RequestMethod.GET)
public String getAllEmployeesXML(Model model)
{
model.addAttribute("employees", getEmployeesCollection()); //getEmployeesCollection 自定义的一个类
return "xmlTemplate";
}
client 的配置,发起一个get请求,把获取的数据 用String 格式化。
private static void getEmployees()
{
final String uri = "http://localhost:8080/springrestexample/employees.xml";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);// 指定转存的响应类型。
System.out.println(result);
}
定制HTTP header
server 端的API的是这样式的
@RequestMapping(value = "/employees", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET) // 定义了方法和类型
public String getAllEmployeesJSON(Model model)
{
model.addAttribute("employees", getEmployeesCollection());
return "jsonTemplate";
}
Client 如下配置
private static void getEmployees()
{
final String uri = "http://localhost:8080/springrestexample/employees";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders(); // 用HttpHeaders 类构造httpheader
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); //添加字段
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers); //封装请求参数
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
System.out.println(result);
}
请求作为指定的结构
client的封装如下
private static void getEmployees()
{
final String uri = "http://localhost:8080/springrestexample/employees";
RestTemplate restTemplate = new RestTemplate();
EmployeeListVO result = restTemplate.getForObject(uri, EmployeeListVO.class); // EmployeeListVO 是我们自定义的一个类
System.out.println(result);
}
get entriy
服务器端例子,构造一个返回的请求类型
@RequestMapping("/handle")
public ResponseEntity<String> handle() {
URI location = ...;
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setLocation(location);
responseHeaders.set("MyResponseHeader", "MyValue");
return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.CREATED);
}
//或者也可以这样
@RequestMapping("/handle")
public ResponseEntity<String> handle() {
URI location = ...;
return ResponseEntity.created(location).header("MyResponseHeader", "MyValue").body("Hello World");
}
客户端解析例子
ResponseEntity<String> entity = template.getForEntity("https://example.com", String.class);
String body = entity.getBody();
MediaType contentType = entity.getHeaders().getContentType();
HttpStatus statusCode = entity.getStatusCode();
POST
DELETE
DELETE有三个方法的重载。
这三个重载方法,传入的变量不一样,支持 MAP 类型 参数与URL,支持 Object对象多值传入,支持 URL。都无返回值。
- void delete(String url, Map<String,?> uriVariables)
- void delete(String url, Object... uriVariables)
- void delete(URI url)
PUT
OpenFeign 用法
用法就像controller 的API 一样,可以对HTTPserver发起请求
首先,需要在启动类里加上注释
可以通过这么几个HTTP client 组件来封装。例如: