Spring Cloud alibaba之Feign

作者: 山巅自相见 | 来源:发表于2022-09-22 16:20 被阅读0次

    JAVA项目中如何实现接口调用?

    1. Httpclient
      Httpclient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持Http协议的客户端编程工具包,并且它支持HTTP协议最新版本和建议。HttpClient相比传统JDK自带的URL Connection,提升了易用性和灵活性,是客户端发送HTTP请求变得容易,提高了开发的效率。
    2. Okhttp
      一个处理网络请求的开源项目,是安卓端最火的轻量级框架,由Square公司贡献,用于代替HttpUrlConnection和Apache HttpClient。OkHttp拥有简洁的API、高校的性能,并支持多种协议(HTTP/2和SPDY)
    3. HttpURLConnection
      HttpURLConnection是Java的标准类,它继承自URLConnection,可用于向指定网站发送GET请求、POST请求。HttpURLConection使用比较复杂,不想HttpClient那样容易使用。
    4. RestTemplate WbClient
      RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程HTTP服务的方法,能够大大提高客户端的编写效率。

    上面介绍的是最常见的几种调用接口的方法,我们下面介绍的方法比上面的更简单、方便,它就是Feign。

    什么是Feign

    Feign是Nexflix开发的声明式、模板化的HTTP客户端,其灵感来自Retrofit、JAXRS-2.0以及WebSocket。Feign可帮助我们更加便捷、优雅地调用HTTP API。
    \color{#FF0000}{Spring Cloud openfeign对Feign进行了增强,使其支持Spring MVC注解,另外还整合了Ribbon和Nacos,从而使得Feign的使用更加方便。}

    优势

    Feign可以做到\color{#FF0000}{使用HTTP请求远程服务时就像调用本地方法一样的体验},开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。它像Dubbo一样,consumer直接调用接口方法调用provider,而不是要通过常规的HttpClient构造请求解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。(简单地说就是A服务的Service接口去调用别的B服务的Controller接口)

    Spring Cloud Alibaba快速整合Opne Feign

    1. 复制order-nacos项目,修改项目名为order-openfeign,修改其它配置。引入依赖
    <!--openfeign远程调用-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    1. 新建Feign接口
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /*
    name指定远程调用的接口所对应的服务名
    path指定远程调用的接口所对应的类的@RequestMapping
     */
    @FeignClient(name = "stock-service", path = "/stock")
    public interface StockFeignService {
        @RequestMapping("/reduct")
        String reduct();
    }
    
    1. 编写订单Controller
    import com.mrZhao.feign.StockFeignService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/order")
    public class OrderController {
        @Autowired
        StockFeignService stockFeignService;
    
        @RequestMapping("/add")
        public String add() {
            System.out.println("下单成功!");
            String reduct = stockFeignService.reduct();
            return "Hello Feign" + reduct;
        }
    }
    
    1. 此时stockFeignService下面有一条红色的波浪线,需要在启动类中配置上开启Feign的注解
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    @SpringBootApplication
    @EnableFeignClients
    public class OrderApplication {
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    }
    

    最终项目结构


    访问订单接口


    日志配置

    1.新建product-nacos子项目,controller

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/product")
    public class ProductController {
        @Value("${server.port}")
        String port;
    
        @RequestMapping("/{id}")
        public String get(@PathVariable Integer id) {
            System.out.println("查询商品" + id);
            return "查询商品" + id + ":" + port;
        }
    }
    

    application.yml

    server:
      port: 8007
    spring:
      application:
        name: product-nacos
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            namespace: public
    

    最终长这样


    1. 在上文中创建的order-openfeign项目中新建配置类
    import feign.Logger;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @author 赵毅梵
     * @create 2022-04-21
     */
    // 此处配置Configuration注解会全局生效 如果想指定对一个的微服务生效 就不能配置
    @Configuration
    public class FeignConfig {
        @Bean
        public Logger.Level feignLoggerLevel() {
            return Logger.Level.FULL;
        }
    }
    
    1. 新建feign接口
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /*
    name指定远程调用的接口所对应的服务名
    path指定远程调用的接口所对应的类的@RequestMapping
     */
    @FeignClient(name = "product-nacos", path = "/product")
    public interface ProductFeignService {
        @RequestMapping("/{id}")
        String get(@PathVariable("id") Integer id);
    }
    
    1. 更新Controller
    import com.mrZhao.feign.ProductFeignService;
    import com.mrZhao.feign.StockFeignService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/order")
    public class OrderController {
        @Autowired
        StockFeignService stockFeignService;
    
        @Autowired
        ProductFeignService productFeignService;
    
        @RequestMapping("/add")
        public String add() {
            System.out.println("下单成功!");
            String reduct = stockFeignService.reduct();
            String s = productFeignService.get(1);
            return "Hello Feign" + reduct + s;
        }
    }
    
    1. application.yml添加配置
    # springboot默认的日志级别时info feign默认的是debug 所以日志级别不输出
    logging:
      level:
        com.mrZhao.feign: debug
    
    1. 启动订单服务、库存服务和商品服务,访问订单接口



      日志信息也打印到了控制台


    契约配置

      Spring Cloud在Feign的基础上做了扩展,使用Spring MVC的疏解来完成Feign的功能。原生的Feign是不支持Spring MVC注解的,如果你想在Spring Cloud中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud中默认的是SpringMvcContract。
      Spring Cloud 1早期版本就是用的原生Feign,随着netflix的停更替换成了Open feign。

    1. 修改契约配置,支持Feign原生的注解
    /**
      *  修改契约配置,支持feign原生的注解
      *  @return
      */
    @Bean
    public Contract feignContract() {
      return new Cotract.Default();
    }
    

    $\color{#FF0000}{注意:修改契约配置后,stock-service不再支持springmvc的注解,需要使用Feign原生的注解}

    1. OrderFeignService中配置使用Feign原生的注解
    @FeignClient(name = "stock-service", path = "/stock", configuration = FeignConfig.class)
    public interface StockFeignService {
        @RequestLine("GET /reduct")
        String reduct();
    }
    
    1. 补充:也可以通过yml方式配置契约
    # feign日志局部配置
    feign:
      client:
        config:
          stock-service:
            loggerLevel: BASIC
            # 设置未默认的契约(还原成原生注解)
            contract: feign.Contract.Default
    

    超时时间设置

    通过 Options 可以配置连接超时时间和读取超时时间,Options 得第一个参数是连接的超时时间(ms),默认值是2s;第二个是请求处理的超时时间(ms),默认是5s。
    全局配置

    import feign.Request;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    // 此处配置Configuration注解会全局生效 如果想指定对一个的微服务生效 就不能加
    @Configuration
    public class FeignConfig {
        @Bean
        public Request.Options options() {
            return new Request.Options(5000, 10000);
        }
    }
    

    yml中配置

    # feign日志局部配置
    feign:
      client:
        config:
          stock-service:
            loggerLevel: BASIC
            # 连接超时时间,默认是2s
            connectTimeout: 5000
            # 请求处理超时时间,默认是5s
            readTimeout: 3000
    

    \color{#FF0000}{补充说明:Feign的底层用的是Ribbon,但超时时间以Feign配置为准}
    测试超时情况:

    相关文章

      网友评论

        本文标题:Spring Cloud alibaba之Feign

        本文链接:https://www.haomeiwen.com/subject/rgxnsrtx.html