2021-03-06_Feign服务原生调用学习笔记

2021-03-08  本文已影响0人  kikop

Feign服务调用学习笔记

1概述

本节简单学习下独立使用Feign的基本用法。Feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。Feign底层默认是使用jdk中的HttpURLConnection发送HTTP请求(没有连接池,保持长连接),feign也提供了httpClient、OKhttp来发送请求。

之所以学习Feign这个功能,主要是考虑:

1.传统采用httpclient(org.apache.httpcomponents)或者okhttp(io.github.openfeign)这样相对较重的框架,对初学者来说编码量与学习曲线都会是一个挑战。

2.而使用spring中RestTemplate,又没有配置化的解决方案。

1.1 Feign底层原理

feign是一个伪客户端,即它不做任何的请求处理。Feign通过处理注解生成request,从而实现简化HTTP API开发的目的,即开发人员可以使用注解的方式定制request api模板,在发送http request请求之前,feign通过处理注解的方式替换掉request模板中的参数,这种实现方式显得更为直接、可理解。

2代码实战

2.1Feign

2.1.1client

2.1.1.1maven依赖

注意点:Feign 10.x 及以上版本是在 Java 8上构建的,应该在 Java 9、10 和 11上工作。对于需要 JDK 6兼容性的用户,请使用 Feign 9.x。

<!--3.1.feign-core-->
<!-- https://mvnrepository.com/artifact/io.github.openfeign/feign-core -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-core</artifactId>
    <version>9.6.0</version>
</dependency>

<!--3.2.feign-jackson-->
<!-- https://mvnrepository.com/artifact/io.github.openfeign/feign-jackson -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-jackson</artifactId>
    <version>9.6.0</version>
</dependency>

2.1.1.2远程服务接口

package com.kikop.mynavivefeign.service.impl;

import com.alibaba.fastjson.JSONObject;
import feign.Headers;
import feign.Param;
import feign.RequestLine;

/**
 * @author kikop
 * @version 1.0
 * @project Name: myspringdemo
 * @file Name: RemoveServiceImpl
 * @desc 远程服务feign包装的接口
 * @date 2021/3/7
 * @time 10:50
 * @by IDE: IntelliJ IDEA
 */
public interface RemoveServiceImpl {

    // 通过@RequestLine指定HTTP协议及URL地址
    @RequestLine("GET /myspringbootdemo/myfeign/say")
    String say();

    // 字符串传参示例
    @RequestLine("GET /myspringbootdemo/myfeign/getStrValue?userName={userName}")
    String getStrValue(@Param(value = "userName") String userName);

    // JSON对象传参示例
    @Headers({"Content-Type: application/json", "Accept: application/json"})
    @RequestLine("POST /myspringbootdemo/myfeign/getObjectValue")
    JSONObject getObjectValue(JSONObject req);

}

2.1.1.3调用测试

package com.kikop.mynavivefeign.test;

import com.alibaba.fastjson.JSONObject;
import com.kikop.mynavivefeign.service.impl.RemoveServiceImpl;
import feign.Feign;
import feign.Request;
import feign.Retryer;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;

public class mytest {

    public static void main(String[] args) {
        try {

            for (int i = 0; i <10 ; i++) {
                getStrValueTest();
            }

        } catch (Throwable ex) {
            System.out.println("----------ex----------");
            ex.printStackTrace();
        }

    }

    private static void sayTest() {
        RemoveServiceImpl removeService = Feign.builder()
                // options方法指定连接超时时长及响应超时时长
                .options(new Request.Options(1000, 3500))
                // retryer方法指定重试策略:最大3次
                .retryer(new Retryer.Default(5000, 5000, 3))
                // target方法绑定接口与服务端地址。返回类型为绑定的接口类型。
                .target(RemoveServiceImpl.class, "http://127.0.0.1:8085");
        System.out.println(removeService.say());
    }

    private static void getStrValueTest() {
        RemoveServiceImpl removeService = Feign.builder()
                // options方法指定连接超时时长及响应超时时长
                .options(new Request.Options(1000, 3500))
                // retryer方法指定重试策略
                .retryer(new Retryer.Default(5000, 5000, 3))
                // target方法绑定接口与服务端地址。返回类型为绑定的接口类型。
                .target(RemoveServiceImpl.class, "http://127.0.0.1:8085");

        String kikop = removeService.getStrValue("kikop");
        System.out.println(kikop);

    }

    private static void getObjectValueTest() {
        RemoveServiceImpl removeService = Feign.builder()
                // pojo对象编码器 
                .encoder(new JacksonEncoder())
                // pojo对象解码器
                .decoder(new JacksonDecoder())
                // options方法指定连接超时时长及响应超时时长
                .options(new Request.Options(1000, 3500))
                // retryer方法指定重试策略
                .retryer(new Retryer.Default(5000, 5000, 3))
                // target方法绑定接口与服务端地址。返回类型为绑定的接口类型。
                .target(RemoveServiceImpl.class, "http://127.0.0.1:8185");

        JSONObject req = new JSONObject();
        req.put("userName", "kikop");
        JSONObject result = removeService.getObjectValue(req);
        System.out.println(result.getString("userName"));
    }
}

2.1.2server(辅助测试)

2.1.2.1后台服务接口

package com.kikop.demo;

import com.alibaba.fastjson.JSONObject;
import com.kikop.mytech.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RequestMapping("/myfeign")
@RestController
@SpringBootApplication
public class DemoApplication {

    @Autowired
    private HelloService helloService;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);

    }

    @RequestMapping("/say")
    public String say() {
        return helloService.say();
    }

    // http://localhost:8085/myspringbootdemo/myfeign/getStrValue?userName=kikop
    @RequestMapping(value = "/getStrValue", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public String getStrValue(@RequestParam String userName) {

        System.out.println("begin getStrValue...");
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        executorService.execute(new MyTaskHandler());
        System.out.println("end getStrValue!");
        return userName.toUpperCase();
    }

    @RequestMapping(value = "/getObjectValue", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public JSONObject getObjectValue(@RequestBody JSONObject user) throws InterruptedException {
        System.out.println("getObjectValue...");
        JSONObject result = new JSONObject();
        result.put("success", true);
        result.put("userName", user.getString("userName").toUpperCase());

        System.out.println("getObjectValue!");
        return result;
    }

}

2.1.2.2服务端配置

server.port=8085
server.servlet.context-path=/myspringbootdemo

mytech.demo.name=kikop
mytech.demo.hobby=swim

3总结

总到来说,Feign的源码实现的过程如下:

参考

1.Feign真正正确的使用方法

https://www.jianshu.com/p/3d597e9d2d67

2feign更正确的使用方法--结合ribbon

https://www.jianshu.com/p/37e915bea7c8

上一篇 下一篇

猜你喜欢

热点阅读