一光年

[SpringCloud-极简示例] 5. 添加Feign,更加优雅的调用ResfulAPI

2019.06.20

目前为止,我们在微服务间的调用都是用的RestTemplate。

  ...
  String URL = serviceInstance.getUri().toURL().toString();
  restTemplate.getForObject(URL + "/" + id, Object.class);

对于多个查询参数的请求,就需要反复去拼接请求路径,如:http://localhost:8080/product?name=a&color=red&comment=abc。对于POST请求来讲,代码的处理就更复杂了。

为了方便API的调用,SpringCloud整合并加强了Netflix开发的Feign,在其中加入了LoadBalancer和Eureka。

导入Feign依赖包

相关包在上一篇已经导入。

  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>LATEST</version>
  </dependency>

实现Feign接口

新建调用的接口类,加入Feign标注,写起来比较像JPA。Feign自动整合了LoadBalancer,只需name中填入请求的服务名,发送请求时可自动识别并发送到对应的实例上。

package com.example.springcloud.comsumer.client;

@FeignClient(name="ms-provider")
public interface ProviderClient {

    @GetMapping(value="/{id}")
    public Object findProductById(@PathVariable("id") Long id);
}

添加@EnableFeignClients

在主程序中加入@EnableFeignClients注解,使Feign生效。

package com.example.springcloud.comsumer;
...

@SpringBootApplication
@EnableFeignClients
public class WsConsumerAApplication {
	
    public static void main(String[] args) {
        SpringApplication.run(WsConsumerAApplication.class, args);
    }
}

调用FeignClient

由于实现了Feign接口,Controller层调用时不在需要手动的去查询ServiceInstance,代码可简化如下:

package com.example.springcloud.comsumer.web;
...

@RestController
@RequestMapping("")
public class DemoController {
	
    @Autowired
    private ProviderClient providerClient;
	
//  @Autowired
//  private RestTemplate restTemplate;
//  @Autowired
//  private LoadBalancerClient loadBalancerClient;

    @GetMapping("/product/{id}")
    public Object getProvider(@PathVariable Long id) {
		
    // 根据负载平衡的设置,自动选择一个Provider服务
//      ServiceInstance serviceInstance = loadBalancerClient.choose("ms-provider");
//      if (serviceInstance == null) {
//          return "找不到服务";
//      }
//		
//      String URL = serviceInstance.getUri().toURL().toString();
//      return restTemplate.getForObject(URL + "/" + id, Object.class);
		
        return providerClient.findProductById(id);
    }
}

重启Consumer服务,在浏览器中输入 http://127.0.0.1:8080/product/1即可看到结果:

{"id":1,"name":"Name-1"}