当前位置: 移动技术网 > IT编程>开发语言>Java > SpringCloud学习笔记(3):使用Feign实现声明式服务调用

SpringCloud学习笔记(3):使用Feign实现声明式服务调用

2019年09月12日  | 移动技术网IT编程  | 我要评论

cv薄荷,印度人,第一小说网

简介

feign是一个声明式的web service客户端,它简化了web服务客户端的编写操作,相对于ribbon+resttemplate的方式,开发者只需通过简单的接口和注解来调用http api。它支持spring mvc注解和jax-rs注解,还支持可插拔式的编码器和解码器。整合了eureka,ribbon和hystrix,具有可插拔、基于注解、负载均衡、服务熔断等一系列便捷功能。

项目介绍

  1. sc-parent,父模块(请参照springcloud学习笔记(1):eureka注册中心)
  2. sc-eureka,注册中心(请参照springcloud学习笔记(1):eureka注册中心)
  3. sc-provider,提供者(请参照springcloud学习笔记(1):eureka注册中心)
  4. sc-consumer-feign,基于feign声明式调用的消费者

基于feign声明式调用的消费者

1.在父模块下创建子模块项目sc-consumer-feign,pom.xml:

<project xmlns="http://maven.apache.org/pom/4.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://maven.apache.org/pom/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelversion>4.0.0</modelversion>
  <parent>
    <groupid>com.cf</groupid>
    <artifactid>sc-parent</artifactid>
    <version>0.0.1-snapshot</version>
  </parent>
  <artifactid>sc-consumer-feign</artifactid>
  
  <dependencies>
    <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-starter-netflix-eureka-client</artifactid>
    </dependency>
    <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-starter-openfeign</artifactid>
    </dependency>
  </dependencies>
</project>

2.创建启动类feign.feignapplication:

package feign;
import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
import org.springframework.cloud.openfeign.enablefeignclients;

@springbootapplication
@enablefeignclients
public class feignapplication {
    public static void main(string[] args) {
        springapplication.run(feignapplication.class, args);
    }
}

3.创建feign声明式接口:feign.inter.bookservice

package feign.inter;
import org.springframework.cloud.openfeign.feignclient;
import org.springframework.web.bind.annotation.getmapping;

@feignclient("sc-provider")
public interface bookservice {
    
    @getmapping("/book/list")
    public string getbooklist();
}

4.创建调用提供者服务的controller:

package provider.controller;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.restcontroller;

@requestmapping("/book")
@restcontroller
public class bookcontroller {
    @getmapping("/list")
    public string getbooklist(){
        return "[\"java入门到放弃\",\"c++入门到放弃\",\"python入门到放弃\",\"c入门到放弃\"]";
    }
}

5.创建application.yml:

server:
  port: 8084

spring:
  application:
    name: sc-consumer-feign
    
eureka:
  client:
    registerwitheureka: false
    serviceurl:
      defaultzone: http://localhost:8080/eureka/

6.依次启动注册中心sc-eureka、提供者sc-provider、消费者sc-consumer-feign,并访问http://www.lhsxpumps.com/_localhost:8084/feign/getbooklist:

feign基于ribbon实现,也具有ribbon负载均衡的特性,可以将调用的提供者服务换成sc-provider-random(请参照springcloud学习笔记(2):使用ribbon负载均衡)来测试。

带参数的请求

上面例子没有涉及到参数的传递,接下来测试下如何使用feign构造带参数的请求,首先对提供者和消费者做如下更改:

//提供者controller添加了两个参数,并打印到控制台。
@requestmapping("/book")
@restcontroller
public class bookcontroller {
    @getmapping("/list")
    public string getbooklist(string param1, integer param2){
        system.out.println(param1 + ":" + param2);
        return "[\"java入门到放弃\",\"c++入门到放弃\",\"python入门到放弃\",\"c入门到放弃\"]";
    }
}


//消费者feign接口和controller添加参数
@feignclient("sc-provider")
public interface bookservice {
    @getmapping("/book/list")
    public string getbooklist(string param1, integer param2);
}

@requestmapping("/feign")
@restcontroller
public class feigncontroller {
    @autowired
    private bookservice bookservice;
    
    @getmapping("/getbooklist")
    public string getbooklist(){
        return bookservice.getbooklist("java", 520);
    }
}

依次启动注册中心sc-eureka、提供者sc-provider、消费者sc-consumer-feign,启动消费者sc-consumer-feign时会启动失败:
java.lang.illegalstateexception: method has too many body parameters: public abstract java.lang.string feign.inter.bookservice.getbooklist(java.lang.string,java.lang.integer)

解决方法1

更改feign接口,为参数添加@requestparam注解:

@feignclient("sc-provider")
public interface bookservice {
    @getmapping("/book/list")   
    public string getbooklist(@requestparam("param1") string param1, @requestparam("param2") integer param2);
}

解决方法2

将参数封装到map里,更改消费者feign接口和controller:

@feignclient("sc-provider")
public interface bookservice {
    @getmapping("/book/list")
    public string getbooklist(@requestparam map<string, object> parammap);
}

@requestmapping("/feign")
@restcontroller
public class feigncontroller {
    @autowired
    private bookservice bookservice;
    
    @getmapping("/getbooklist")
    public string getbooklist(){
        map<string,object> parammap = new hashmap<string, object>();
        parammap.put("param1", "java");
        parammap.put("param2", 520);
        return bookservice.getbooklist(parammap);
    }
}

在参数较多的情况下,该方式可以简化feign接口的编写。

自定义类型的参数

openfeign的@querymap注解支持将自定义类型用于get参数映射,由于@querymap和spring不兼容,spring cloud openfeign提供了一个等价的@springquerymap注解,可以用于自定义类型和map类型的参数映射。下面将使用自定义类型params作为参数,使用@springquerymap注解来处理自定义类型的参数映射。

1.分别在提供者和消费者中创建类params(可以建一个公共模块,然后在提供者和消费者中添加依赖):

public class params {
    private string param1;
    
    private integer param2;

    public string getparam1() {
        return param1;
    }

    public void setparam1(string param1) {
        this.param1 = param1;
    }

    public integer getparam2() {
        return param2;
    }

    public void setparam2(integer param2) {
        this.param2 = param2;
    }
    
    @override
    public string tostring() {
        return "params [param1=" + param1 + ", param2=" + param2 + "]";
    }

    public params(string param1, integer param2) {
        this.param1 = param1;
        this.param2 = param2;
    }

    public params() {}
}

2.更改提供者和消费者相关类

//提供者
@requestmapping("/book")
@restcontroller
public class bookcontroller {
    @getmapping("/list")
    public string getbooklist(params params){
        system.out.println(params.tostring());
        return "[\"java入门到放弃\",\"c++入门到放弃\",\"python入门到放弃\",\"c入门到放弃\"]";
    }
}

//消费者
@feignclient("sc-provider")
public interface bookservice {
    @getmapping("/book/list")
    public string getbooklist(@springquerymap params params);
}

@requestmapping("/feign")
@restcontroller
public class feigncontroller {
    @autowired
    private bookservice bookservice;
    
    @getmapping("/getbooklist")
    public string getbooklist(){    
        params params = new params("java", 520);
        return bookservice.getbooklist(params);
    }
}

3.依次启动注册中心sc-eureka、提供者sc-provider、消费者sc-consumer-feign,并访问http://localhost:8084/feign/getbooklist,提供者控制台输出:

params [param1=java, param2=520]

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网