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 + "\nRequestParam name : " + name + "\nRequestBody 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();
    }


}

 

 
posted @ 2021-02-18 23:53  Goosander  阅读(187)  评论(0编辑  收藏  举报