• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Feign

武飞扬头像
panghuhu-Li
帮助1

1.Feign介绍

feign是一个http请求调用的轻量级框架,可以以java接口注解的方式来调用http请求。springcloud引入feign并集成了ribbon实现客户端负载均衡,作为SpringCloud的RPC框架

Feign解决了什么问题?

封装了Http调用流程,更适合面向接口化的编程思想

2.Feign学习

1.创建新的maven项目

2.导包

	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
    </parent>

    <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>
            <version>2.2.2.RELEASE</version>
        </dependency>
    </dependencies>
学新通

3.创建启动类

@SpringBootApplication
@EnableFeignClients
public class FeignApplication {


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

4.编写FeignService

//value属性在微服务里面是服务名,但是我们当前这不是微服务项目,所以该值无用,但是又必填
@FeignClient(value = "asdf", url = "http://httpbin.org")
public interface FeignService {

    @GetMapping("get")
    String firstTest();
}

5.编写测试的controller

@RestController
public class TestController {

    @Resource
    private FeignService feignService;

    @GetMapping("test")
    public String test(){
        return feignService.firstTest();
    }
}

3、测试过程

1、在浏览器中对feign项目中的接口发起请求,地址:http://127.0.0.1:9090/get。

2、feign项目通过feign框架,对boot项目发起请求,访问对应接口。

3、boot项目收到请求,把数据返回给feign。

4、feign项目吧boot项目返回的数据,传输到浏览器当中。

举例

@FeignClient(value = "panghuhu", url = "http://127.0.0.1:8080")
public interface StudentService {

    //这里的GetMapping应和调用接口的注解一致,并且feign能自动反序列化成对应的对象
    @GetMapping("selectByNo")
    FeignResult<Student> getStudent(
            //@RequestParam("nou")用来指示调用接口的参数名
            @RequestParam("nou") String no);
}


@RestController
public class TestController {

    @Resource
    private StudentService studentService;

    @Resource
    private FeignService feignService;

    @GetMapping("get")
    public FeignResult<Student> get() {
        FeignResult<Student> student = studentService.getStudent("1002");
        System.out.println(student);
        return student;
    }

}

学新通

4、原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pb5ZATAh-1654674573549)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220608084842800.png)]

5、RPC(Remote Produce Call Protocal)

RPC,远程过程调用,可以像调用本地服务一样调用远端服务

远程过程调用,通常由服务端,客户端,通信网络三部分组成

RPC协议的核心,通信协议,编码协议,序列化格式

6、手动模拟一个rpc框架

rpc-server

服务端模块,用来提供服务

rpc-client

客户端模块,用来调用服务

rpc-common

公共模块,用来给接口提供动态代理类

rpc-bussiness

用来定义client和server之间的交互接口

数据交互流程

主要是rpc-client和rpc-server之间的数据交互,client调用bussiness里提供的接口,client和server之间使用socket进行数据传输那么server就需要代理告诉他,client调用的事哪个接口,哪个方法,参数有哪些。

客户端代理类

public class ProxyHandler implements InvocationHandler {

    private String ip;
    private int port;

    public ProxyHandler(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

    @Override
    //动态代理方法,主要是给接口生成动态代理类,可以向调用本地方法一样调用远程方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //创建socket对象,连接目标服务器进行数据传输
        Socket socket = new Socket(ip, port);

        //获取客户端调用的接口
        Class<?>[] callInterface = proxy.getClass().getInterfaces();
        //获取客户端调用的方法名
        String name = method.getName();
        //获取客户端该方法的参数类型列表,因为方法可以重载,如果没有类型列表的话,就无法确定到底调用的事哪个方法
        Class<?>[] types = method.getParameterTypes();
        //向服务端传输数据使用的
        ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
        //输入流是从服务端读取数据使用的
        ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
        out.writeObject(callInterface);
        out.writeUTF(name);
        out.writeObject(types);
        out.writeObject(args);
        //主动刷新流数据,把数据推送到服务端
        out.flush();

        //接受服务端返回的对象
        Object object = input.readObject();

        if (object instanceof Throwable) {
            throw (Throwable) object;
        }
        socket.shutdownOutput();
        return object;
    }
}

学新通

客户端获取代理类对象

public class RpcClient {

    //获取接口代理类对象
    public static <T> T getService(Class<T> clazz, String ip, int port) {
        ProxyHandler handler = new ProxyHandler(ip, port);

        Object o = Proxy.newProxyInstance(RpcClient.class.getClassLoader()
                , new Class<?>[]{clazz}, handler);
        return (T) o;
    }

}

服务端代理类

public class RpcProvider {

    private int port = 8080;

    public void start() throws Exception {
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("服务端开启成功");
        //死循环,让程序一致运行,持续见天客户端的请求
        while (true) {
            //accept方法会租了,知道有请求过来为止
            Socket socket = serverSocket.accept();
            System.out.println("收到客户端的请求");
            ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
            ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());

            //服务端读取数据的顺序一定要与客户写入的顺序一致
            Class<?>[] callInterface = (Class<?>[]) in.readObject();
            String name=in.readUTF();
            Class<?>[] types= (Class<?>[]) in.readObject();
            Object[] args= (Object[]) in.readObject();

            out.writeObject("ok");
            out.flush();
            out.close();
            in.close();
            socket.close();
        }
    }

    public static void main(String[] args) throws Exception {
        RpcProvider provider=new RpcProvider();
        provider.start();
    }
}
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgjkkfc
系列文章
更多 icon
同类精品
更多 icon
继续加载