我是靠谱客的博主 大意唇膏,最近开发中收集的这篇文章主要介绍Springboot整合 openfeign(基于最新Hoxton.SR8),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

    • 项目整体结构
    • 依赖
    • openfeign的一些配置
    • order-service-api
    • order-service
    • pay-service
    • 测试
    • 源码分析
    • 源码下载

项目整体结构

在这里插入图片描述

说明:

  • 所有公共依赖都放在了父pom中,API接口抽离放在单独模块

依赖

<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
</properties>

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

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

这里模拟支付服务调用订单服务,订单 order-service 会依赖于 order-service-api, pay-service 会依赖于 pay-service-api,同时因为要调用 订单服务,所以也会依赖于 order-service-api

在这里插入图片描述

在这里插入图片描述

这样做的好处是抽离了公共的接口,同事将model放在了公共API采用继承方式减少重复代码,不采用这种方式模块间的相互调用就会写重复的model和接口

openfeign的一些配置

feign:
  client:
    config:
    # 全局级别配置
      default:
        connectTimeout: 5000
        readTimeout: 5000
        # 只打印基本信息,包括请求方法、请求地址、响应状态码、请求时长
        loggerLevel: basic

我们也可以采用 @Configuration的 方式来配置 feign,如果配置文件和 @Configuration都配置了,配置文件将会覆盖@configuration 值,如果希望将优先级更改为@configuration,可以将 feign.client.default-to-properties 更改为 false
在 Feign 中,定义了四种日志级别:

  • NONE:不打印日志
  • BASIC:只打印基本信息,包括请求方法、请求地址、响应状态码、请求时长
  • HEADERS:在 BASIC 基础信息的基础之上,增加请求头、响应头
  • FULL:打印完整信息,包括请求和响应的所有信息。

更多信息请参考 springboot

order-service-api

结构:
在这里插入图片描述

  • Order
@Data
public class Order {

    /**
     * 订单号
     */
    private String orderNo;
    /**
     * 价格
     */
    private BigDecimal price;
    /**
     * 商品数量
     */
    private Integer orderCount;
}
  • OrderService
@RestController
@RequestMapping("/order")
public interface OrderService {

    @GetMapping(value = "/get-order",headers = {"Accept=application/json"})
    Order getOrder(@RequestParam("orderNo")String orderNo);
}

order-service

结构:
在这里插入图片描述

  • application.properties
server.port=8080
spring.application.name=order-service
  • OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {

    @Override
    public Order getOrder(String orderNo) {
        System.out.println("收到的订单号为: " + orderNo);
        Order order = new Order();
        order.setOrderNo("123456");
        order.setOrderCount(5);
        order.setPrice(new BigDecimal("52.6"));
        return order;
    }
}
  • OrderController
public class OrderController implements OrderService{

    @Autowired
    OrderService orderService;


    @Override
    public Order getOrder(String orderNo) {
        return orderService.getOrder("123");
    }
}

pay-service

目录结构:
在这里插入图片描述

  • PayController
public class PayController implements PayService{


    @Autowired
    PayService payService;

   @Override
    public boolean pay() {
        payService.pay();
       return true;

    }
}
  • OrderServiceApi
@FeignClient(name = "order-service",url = "127.0.0.1:8080")
public interface OrderServiceApi extends OrderService {
}

这里name 是服务名 即订单服务,url是订单服务的访问地址,这里因为没有用到注册中心,所以需要写url

  • PayServiceImpl
@Service
public class PayServiceImpl implements PayService {


    @Autowired
    private OrderServiceApi orderServiceApi;



    @Override
    public boolean pay() {
        Order order = orderServiceApi.getOrder("123456");
        System.out.println("获取到订单号" + order.getOrderNo());
        return true;
    }
}

这里的url也是支持占位符的 类似 这种 url = "${order.service.baseUrl} 然后将地址写在配置文件中也是可以的

项目大致结构是这样,pay-service-api 和 order-service-api类似,感兴趣可以自己去源码查看

然后我们需要在 order-service 和 pay-service 的启动类开启使用Fegin的注解
在这里插入图片描述

测试

然后同时启动 order-service 和 pay-service,注意自己在 配置文件配置不同的端口,idea启动多个实例请查看我以前的博客教程

然后访问调用 支付接口

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里可以看到调用Order-service 服务已经成功了

源码分析

首先我们 从 启动类的 @EnableFeignClients 注解分析
在这里插入图片描述
这里可以看到导入了一个配置类 EnableFeignClients

那么很明显 EnableFeignClients 配置类会将FeignClient注解的类注册到Spring IOC容器里供我们使用,我们来看看看 EnableFeignClients 核心代码
在 registerDefaultConfiguration 方法中
在这里插入图片描述
首先会去检测 EnableFeignClients 中是否配置 clients,如果没有配置则将 通过 @FeignClient 注解去找到相应的客户端,放入BeanDefinitionBuilder,然后根据BeanDefinitionBuilder得到beanDefinition,最后beanDefinition式注入到ioc容器
在这里插入图片描述
通过包扫描获取到 @FeignClient 的类的 beanDefinition
在这里插入图片描述

这里再调用 registerFeignClient 注入到IOC容器中
在这里插入图片描述
在这里插入图片描述

注入bean之后,通过jdk的代理,当请求Feign Client的方法时会被拦截,然后通过ReflectiveFeign类获取对象,代码如下:

public <T> T newInstance(Target<T> target) {
        Map<String, MethodHandler> nameToHandler = this.targetToHandlersByName.apply(target);
        Map<Method, MethodHandler> methodToHandler = new LinkedHashMap();
        List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList();
        Method[] var5 = target.type().getMethods();
        int var6 = var5.length;

        for(int var7 = 0; var7 < var6; ++var7) {
            Method method = var5[var7];
            if (method.getDeclaringClass() != Object.class) {
                if (Util.isDefault(method)) {
                    DefaultMethodHandler handler = new DefaultMethodHandler(method);
                    defaultMethodHandlers.add(handler);
                    methodToHandler.put(method, handler);
                } else {
                    methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
                }
            }
        }

        InvocationHandler handler = this.factory.create(target, methodToHandler);
        T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
        Iterator var12 = defaultMethodHandlers.iterator();

        while(var12.hasNext()) {
            DefaultMethodHandler defaultMethodHandler = (DefaultMethodHandler)var12.next();
            defaultMethodHandler.bindTo(proxy);
        }

        return proxy;
    }

源码下载

最后

以上就是大意唇膏为你收集整理的Springboot整合 openfeign(基于最新Hoxton.SR8)的全部内容,希望文章能够帮你解决Springboot整合 openfeign(基于最新Hoxton.SR8)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部