告别 RestTemplate,OpenFeign 才是微服务通信的正确姿势

目录

一、OpenFeign快速使用

1.引入依赖

2.添加注解

3.编写OpenFeign的客⼾端

4.修改远程调用

5.测试

二、OpenFeign参数传递

1.单个参数

2.多个参数

4.传递对象

5.传递JSON

三、OpenFeign的最佳实践

1.继承的方式

2.抽取的方式

OpenFeign 是 Spring Cloud 提供的一种 声明式 HTTP 客户端。它的核心作用是,让我们 像调用本地方法一样调用远程服务的 HTTP 接口,不用自己写 RestTemplate 的请求代码。

回顾之前.......中出现的订单服务远程调用产品服务中,是通过RedisTemplate实现的,参考代码如下:

public OrderInfo selectOrderById(Integer orderId) {
    OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
    String url = "http://product-service/product/"+ orderInfo.getProductId();
​
    ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
    orderInfo.setProductInfo(productInfo);
​
    return orderInfo;
}

当前代码功能上没有问题,但是存在一些细节上的问题:

1.封装比较臃肿,URL复杂时可能容易出错。

2.代码可读性比较差,风格不统一。

一、OpenFeign快速使用

1.引入依赖

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

2.添加注解

在order-service的启动类添加注解 @EnableFeignClients ,开启OpenFeign的功能

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

3.编写OpenFeign的客⼾端

@FeignClient(value = "product-service", path = "/product")
public interface ProductApi {
    @RequestMapping("/{productId}")
    ProductInfo getProductById(@PathVariable("productId") Integer productId);
}

@FeignClient参数说明:

name:指定FeignClient的名称,也就是微服务的名称,用于服务发现,Feign底层会使用Spring Cloud LoadBalance进行负载均衡,也可以使用url 属性指定⼀个具体的url。

path:定义当前FeignClient的统⼀前缀。

4.修改远程调用

@Autowired
private ProductApi productApi;
​
public OrderInfo selectOrderById(Integer orderId) {
    OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
    
    ProductInfo productInfo = productApi.getProductById(orderInfo.getProductId());
    
    orderInfo.setProductInfo(productInfo);
    return orderInfo;
}

5.测试

启动服务,访问接口,测试远程调用:http://127.0.0.1:8080/order/1

此时就实现了更优雅的远程调用!

二、OpenFeign参数传递

1.单个参数

服务提供方

@RestController
@RequestMapping("/product")
public class ProductController {
​
    @RequestMapping("/p1")
    public String p1(Integer id){
        return "p1接收到参数:"+id;
    }
}

OpenFeign客户端

@FeignClient(value = "product-service", path ="/product")
public interface ProductApi {
​
    @RequestMapping("/p1")
    String p1(@RequestParam("id") Integer id);
}

注意: @RequestParam 做参数绑定, 不能省略

服务消费方

@RequestMapping("/feign")
@RestController
public class TestFeignController {
​
    @Autowired
    private ProductApi productApi;
​
    @RequestMapping("/o1")
    public String o1(Integer id) {
        return productApi.p1(id);
    }
}

2.多个参数

服务提供方

@RequestMapping("/p2")
public String p2(Integer id,String name){
    return "p2接收到参数,id:"+id +",name:"+name;
}

OpenFeign客户端

@RequestMapping("/p2")
String p2(@RequestParam("id")Integerid,@RequestParam("name")String name);

服务消费方

@RequestMapping("/o2")
public String o2(@RequestParam("id")Integer id,@RequestParam("name")String name{
​
    return productApi.p2(id,name);
}

4.传递对象

服务提供方

@RequestMapping("/p3")
public String p3(ProductInfo productInfo){
​
    return "接收到对象, productInfo:"+productInfo;
}

OpenFeign客户端

@RequestMapping("/p3")
String p3(@SpringQueryMap ProductInfo productInfo);

服务消费方

@RequestMapping("/o3")
public String o3(ProductInfo productInfo){
​
     return productApi.p3(productInfo);
}

5.传递JSON

服务提供方

@RequestMapping("/p4")
public String p4(@RequestBody ProductInfo productInfo) {
​
    return "接收到对象, productInfo:"+productInfo;
}

OpenFeign客户端

@RequestMapping("/p4")
String p4(@RequestBody ProductInfo productInfo);

服务消费方

@RequestMapping("/o4")
public String o4(@RequestBody ProductInfo productInfo) {
​
    return productApi.p4(productInfo);
}

三、OpenFeign的最佳实践

1.继承的方式

我们可以定义好⼀个接口,服务提供方实现这个接口,服务消费方编写Feign接口的时候, 直接继承这个接口。

定义接口

public interface ProductInterface {
​
    @RequestMapping("/{productId}")
    ProductInfo getProductById(@PathVariable("productId") Integer productId);
​
    @RequestMapping("/p1")
    String p1(@RequestParam("id") Integer id);
​
    @RequestMapping("/p2")
    String p2(@RequestParam("id")Integer id,@RequestParam("name")String name);
​
    @RequestMapping("/p3")
    String p3(@SpringQueryMap ProductInfo productInfo);
​
    @RequestMapping("/p4")
    String p4(@RequestBody ProductInfo productInfo);
}

服务提供方实现接口

@RequestMapping("/product")
@RestController
public class ProductController implements ProductInterface {
​
    @Autowired
    private ProductService productService;
​
    @RequestMapping("/{productId}")
    public ProductInfo getProductById(@PathVariable("productId") Integer productId){
        
        return productService.selectProductById(productId);
    }
​
    @RequestMapping("/p1")
    public String p1(Integer id){
    
        return "p1接收到参数:"+id;
    }
​
    @RequestMapping("/p2")
    public String p2(Integer id,String name){
​
        return "p2接收到参数,id:"+id +",name:"+name;
    }
​
    @RequestMapping("/p3")
    public String p3(ProductInfo productInfo){
​
        return "接收到对象, productInfo:"+productInfo;
    }
​
    @RequestMapping("/p4")
    public String p4(@RequestBody ProductInfo productInfo){
​
        return "接收到对象, productInfo:"+productInfo;
    }
​
}

服务消费方继承接口

@FeignClient(value = "product-service", path = "/product")
    public interface ProductApi extends ProductInterface {
}

2.抽取的方式

将Feign的Client抽取为⼀个独立的模块,并把涉及到的实体类等都放在这个模块中,打成⼀个jar包,服务消费方只需要依赖该jar包即可,这种方式在企业中比较常见,jar包通常由服务提供方来实现。

①创建module,命名为product-api

②引入依赖

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

③编写api

复制 ProductApi, ProductInfo 到product-api模块中。

④打jar包

通过Maven打包

⑤服务消费方引入jar包

⑥在启动类添加扫描路径

@EnableFeignClients(clients = {ProductApi.class})
@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        
        SpringApplication.*run*(OrderServiceApplication.class, args);
    }
}

两种方式对比

在实际项目中,抽取方式比继承方式更为常用,因为它更加灵活,并且符合面向接口编程的原则,同时也避免了继承可能带来的紧耦合问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值