Feign简介
Feign是Netflix开发的声明式,模板化的HTTP客户端,其灵感来自Retrofit,JAXRS-2.0以及WebSocket.
Feign可帮助我们更加便捷,优雅的调用HTTP API。
在SpringCloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。
Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
SpringCloud对Feign进行了增强,使Feign支持了SpringMVC注解,并整合了Ribbon和Eureka,
从而让Feign的使用更加方便
Feign和Ribbon的联系
Ribbon是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具。它可以 在客户端 配置
RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate 模拟http请求,步骤相当繁琐。
Feign 是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。采用接口的
方式, 只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方
法即可, 不需要自己构建http请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方
法,使得编写客户端变得非常容易
整合Feign
pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
1 @SpringBootApplication 2 @EnableFeignClients 3 public class OrderServiceApplication { 4 5 public static void main(String[] args) { 6 SpringApplication.run(OrderServiceApplication.class, args); 7 } 8 }
Web层
1 @RestController 2 @RequestMapping("/api/v1/order") 3 public class OrderController { 4 5 6 @Autowired(required = false) 7 private ProductOrderServiceImpl productOrderService; 8 9 10 @RequestMapping("/save") 11 public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId){ 12 13 return productOrderService.save(userId, productId); 14 } 15 16 }
Bo类
/** * 商品订单实体类 */ public class ProductOrder implements Serializable { private int id; /** * 商品名称 */ private String productName; /** * 订单号 */ private String tradeNo; /** * 价格,分 */ private int price; private Date createTime; private int userId; private String userName; public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getTradeNo() { return tradeNo; } public void setTradeNo(String tradeNo) { this.tradeNo = tradeNo; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } }
Fegin客户端
1 /** 2 * 商品服务客户端 3 */ 4 @FeignClient(name = "product-service") 5 public interface ProductClient { 6 7 8 @GetMapping("/api/v1/product/find") 9 String findById(@RequestParam(value = "id") int id); 10 11 12 } 13
Service层
1 @Service 2 public class ProductOrderServiceImpl { 3 4 5 @Autowired(required = false) 6 private ProductClient productClient; 7 8 public ProductOrder save(int userId, int productId) { 9 10 String response = productClient.findById(productId); 11 12 JsonNode jsonNode = JsonUtils.str2JsonNode(response); 13 14 ProductOrder productOrder = new ProductOrder(); 15 productOrder.setCreateTime(new Date()); 16 productOrder.setUserId(userId); 17 productOrder.setTradeNo(UUID.randomUUID().toString()); 18 productOrder.setProductName(jsonNode.get("name").toString()); 19 productOrder.setPrice(Integer.parseInt(jsonNode.get("price").toString())); 20 return productOrder; 21 } 22 23 } 24
Util类
1 /** 2 * json工具类 3 */ 4 public class JsonUtils { 5 6 private static final ObjectMapper objectMappper = new ObjectMapper(); 7 8 /** 9 * json字符串转JsonNode对象的方法 10 */ 11 public static JsonNode str2JsonNode(String str){ 12 try { 13 return objectMappper.readTree(str); 14 } catch (IOException e) { 15 return null; 16 } 17 } 18 19 20 }
注:eureka-server和prduct-service参考前面的,直接启动
测试:
http://localhost:8781/api/v1/order/save?user_id=1&product_id=1
{ "id": 0, "productName": ""iphonex data from port=8771"", "tradeNo": "6b9b6530-a1f8-42d8-9a17-1beda890a91e", "price": 9999, "createTime": "2019-10-17T05:58:09.717+0000", "userId": 1, "userName": null } { "id": 0, "productName": ""iphonex data from port=8773"", "tradeNo": "6b668929-4280-44cc-9c7c-401ca85e6550", "price": 9999, "createTime": "2019-10-17T06:32:16.971+0000", "userId": 1, "userName": null } { "id": 0, "productName": ""iphonex data from port=8772"", "tradeNo": "3e1a4887-98e8-4910-93fb-4758c508c643", "price": 9999, "createTime": "2019-10-17T06:32:32.355+0000", "userId": 1, "userName": null }