zoukankan      html  css  js  c++  java
  • Spring Cloud Alibaba Feign 声明式服务调用

    1.使用 Feign 调用服务

     创建一个服务提供者,整合 Nacos
     创建一个服务消费者,整合 Nacos
     服务消费者添加 Feign 依赖
     服务消费者创建 Feign 客户端接口
     服务消费者使用 Feign 接口调用服务提供者
     启动并测试

    服务提供者
    添加 Nacos 依赖:

    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibabanacos-discovery</artifactId>
    </dependency>
    启动类添加服务发现注解
    @EnableDiscoveryClient
    属性配置:
    server:
    port: 8081
    spring:
    application:
    name: service-provider
    cloud:
    nacos:
    discovery:
    server-addr: localhost:8848
    创建 Feign 接口:
    服务消费者
    添加 Feign 依赖:
    <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    添加 Feign 注解:
    @EnableFeignClients
    创建 Feign 接口:
    package com.example.demo;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    @FeignClient(name="service-provider")
    public interface HelloService {
        @GetMapping("/hello")
        public String hello(@RequestParam("name") String name);
    }

    调用 Feign 接口:

    package com.example.demo;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class TestController {
    
        @GetMapping("/hi")
        public String hi() {
            return "hi";
        }
    
        @Autowired
        HelloService helloService;
    
        @GetMapping("/hello")
        public String hello(@RequestParam String name) {
            return helloService.hello(name);
        }
    }

    2.Feign 工作原理

    3.Feign 日志配置

    Feign 日志级别

    局部日志配置,代码方式配置日志

    配置文件中设置 Feigin client 接口的日志级别
    logging:
    level:
    com.example.serviceconsumerfeign.feiginclient: debug
    创建日志级别配置类
    package com.example.demo;
    
    import feign.Logger;
    import org.springframework.context.annotation.Bean;
    
    public class FeignClientConfig {
        @Bean
        public Logger.Level level(){
            return Logger.Level.FULL;
        }
    }
    Feiginclient接口中引用
    package com.example.demo;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    @FeignClient(name="service-provider",configuration = FeignClientConfig.class)
    public interface HelloService {
        @GetMapping("/hello")
        public String hello(@RequestParam("name") String name);
    }

    局部日志配置,属性方式配置日志

    配置文件中设置 Feigin client 接口的日志级别
     logging:
       level:
         com.example.serviceconsumerfeign.feiginclient: debug
    设置目标调用服务的日志级别
    feign:
      client:
        config:
           service-provider: # 想要调用的服务名称
             loggerLevel: FULL
     
    全局方式配置日志
    局部的日志配置是针对某个 Feign 接口的,如果需要配置的接口比较多,比较适合使用全局配置。 全局配置同样可以通过代码的方式或者属性方式来配置。
    代码方式
    @SpringBootApplication
    // 把日志配置类定义到启动类中
    @EnableFeignClients(defaultConfiguration = FeignClientDemoConfig.class)
    public class ServiceConsumerFeignApplication {
      public static void main(String[] args) {
        SpringApplication.run(
        ServiceConsumerFeignApplication.class, args);
    }}
    属性方式
    feign:
      client:
        config:
          default: # 全局配置
            loggerLevel: FULL

    4.多参数传递

    服务提供者

        @GetMapping("/user")
        public User getUser(User user){
            return User.builder().id(1).name(user.getName()).city(user.getCity()).email("a@a.com").build();
        }
     服务消费者 参数注解,SpringMVC 的 get 方法支持直接绑定 POJO,而 Feign 并未覆盖所有 SpringMVC 功能,不能直接绑定 POJO,但解决起来也很简单,只需要添加一个注解 @SpringQueryMap。
    @FeignClient(name="service-provider")
    public interface FeignClientUser {
      @GetMapping("/getUser")
      String getUser(@SpringQueryMap User user);
    }
    服务消费者 独立参数,这是最为直观的方式,URL中有几个参数,Feign 接口中的方法就定义几个参数。使用 @RequestParam 注解指定请求的参数。
    @FeignClient(name="service-provider")
    public interface FeignClientUser {
     @GetMapping("/getUser")
     String getUser_param(@RequestParam("id") Long id, @RequestParam("name") String name, @RequestParam("age") int age);
    }

    5.复杂参数形式与文件上传

    服务提供者 复杂参数形势
    @RestController
    public class DemoController {
     @RequestMapping(path = "/demo_complex/{id}",
     method = RequestMethod.POST)
     public String demo_complex(@PathVariable("id") String id,@RequestBody Map<String, Object> map,@RequestParam String name) {
    Object json
    = JSON.toJSON(map); return "PathVariable id :" + id + " RequestParam name : " + name + " RequestBody map: " + json.toString(); } }
    服务提供者 文件上传
    package com.example.demo;
    
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    @RestController
    public class UploadController {
        @PostMapping(value = "/uploadFile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
        public String fileupload(MultipartFile file) throws Exception {
            return file.getOriginalFilename();
        }
    }

    服务消费者 处理复杂参数形式

    @FeignClient(name="service-provider")
    public interface FeignClientDemo {
     @RequestMapping(path = "/demo_complex/{id}",method = RequestMethod.POST )
     public String demo_complex(@PathVariable("id") String id,@RequestBody Map<String, Object> map,@RequestParam String name) ;
    }

    服务消费者 文件上传

    添加依赖:

    <dependency>
     <groupId>io.github.openfeign.form</groupId>
     <artifactId>feign-form</artifactId>
     <version>3.8.0</version>
    </dependency>
    <dependency>
     <groupId>io.github.openfeign.form</groupId>
     <artifactId>feign-form-spring</artifactId>
     <version>3.8.0</version>
    </dependency>
    FeignClient 中定义:
    @RequestMapping(value = "/uploadFile", method = RequestMethod.POST,produces = {MediaType.APPLICATION_JSON_UTF8_VALUE},consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    String handleFileUpload(@RequestPart(value = "file") MultipartFile file);
    Controller 中定义:
    @PostMapping(value = "/upload")
    public String imageUpload( MultipartFile file ) throws Exception{
      return feignClientDemo.handleFileUpload(file);
    }

    6.Feign Client 改用 HTTPClient 与 OKHTTP

    Feign 的 HTTP 客户端支持 3 种框架:HttpURLConnection(默认)、HttpClient、OKhttp。传统的 HttpURLConnection 是 JDK 自带的,并不支持连接池,效率非常低。为了提高效率,可以通过连接池提高效率,appache httpclient 和 okhttp 都是支持链接池的。

    替换 HttpClient
    添加依赖
    <dependency>
     <groupId>io.github.openfeign</groupId>
     <artifactId>feign-httpclient</artifactId>
    </dependency>
    属性配置,开启 HttpClient 的支持。
    feign:
     httpclient:
       enabled: true
       # 最大连接数
       max-connections: 200 
       # 单个路由的最大连接数
       max-connections-per-route: 50
    开启日志,验证是否输出 HttpClient 相关日志
    logging:
     level:
       org.apache.http.wire: debug
       org.apache.http.headers: debug
     
    替换 OKHttp
    添加依赖
    <dependency>
     <groupId>io.github.openfeign</groupId>
     <artifactId>feign-okhttp</artifactId>
     <version>10.2.0</version>
    </dependency>
    <dependency>
      <groupId>com.parkingwang</groupId>
      <artifactId>okhttp3-loginterceptor</artifactId>
      <version>0.5</version>
    </dependency>
    属性配置,开启 OKHttp 的支持。
    feign:
     client:
      config:
       default: # 全局配置
        loggerLevel: FULL
    httpclient:
     enabled: false
     max-connections: 200
     max-connections-per-route: 50
    okhttp:
     enabled: true
    OKHttp 配置类,配置连接池,以及日志拦截器
    package com.example.demo;
    
    import com.parkingwang.okhttp3.LogInterceptor.LogInterceptor;
    import feign.Feign;
    import okhttp3.ConnectionPool;
    import okhttp3.OkHttpClient;
    import org.springframework.boot.autoconfigure.AutoConfigureBefore;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.cloud.openfeign.FeignAutoConfiguration;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.concurrent.TimeUnit;
    
    @Configuration
    @ConditionalOnClass(Feign.class)
    @AutoConfigureBefore(FeignAutoConfiguration.class)
    public class FeignClientOkHttpConfiguration {
    
        @Bean
        public OkHttpClient okHttpClient() {
            // 配置项:
            // 1.连接超时时间
            // 2.响应超时时间
            // 3.写超时时间
            // 4.自动重连
            // 5.配置连接池
            // 6.添加日志拦截器
            return new OkHttpClient.Builder()
                    .connectTimeout(20, TimeUnit.SECONDS)
                    .readTimeout(20, TimeUnit.SECONDS)
                    .writeTimeout(20, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true)
                    .connectionPool(new ConnectionPool())
                    .addInterceptor(new LogInterceptor())
                    .build();
        }
    
    
    }
     
  • 相关阅读:
    手游渠道分成的那些坑来等你跳
    [手游新项目历程]-43-sql关键字解决
    一些相似词的区别
    程序员之间的“笑料”
    程序员之间的“笑料”
    2014游戏圈员工跳槽必看
    2014游戏圈员工跳槽必看
    游戏应该怎么做-美术
    游戏应该怎么做-美术
    [手游新项目历程]-44-gdb
  • 原文地址:https://www.cnblogs.com/lilb/p/14414128.html
Copyright © 2011-2022 走看看