说明:该文章只是简单描述了如何进行通信,并没有关于feign的详细注解和高级使用。(大佬看看我写的有没有问题也是可以的)。

流程简述:一个程序作为eureka服务端供其余两个应用注册,另外两个应用注册后使用feign进行应用间通信。

使用环境:JDK 8、SpringBoot: 2.1.3、SpringCloud:Greenwich.SR1
版本不一致可能会导致莫名奇妙的错误。

1、eureka服务端的创建(eureka-server):

(1)打开idea创建springboot项目,在选模块的时候记得选上下图所示模块:

jeecg 微服务feign调用 eureka feign微服务间通信_spring

 

(2)给出pom.xml和application.yml的配置文件(只要你按照(1)选了Eureka Server模块,pom.xml应该是和我一样的)
pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml配置:

server:
  #服务端口
  port: 8761
spring:
  application:
    name: eureka-server
eureka:
  client:
    # 禁止自己注册自己
    register-with-eureka: false
    # 服务开启的url
    service-url:
          defaultZone: http://localhost:8761/eureka/

 

(3)在启动类上加上注解:@EnableEurekaServer

jeecg 微服务feign调用 eureka feign微服务间通信_jeecg 微服务feign调用_02

 

2、两个eureka客户端的创建(feign-client、feign-server):

    首先创建feign-client应用

(1)创建springboot应用,在选择模块的时候选择下图所示的两个模块:

jeecg 微服务feign调用 eureka feign微服务间通信_jeecg 微服务feign调用_03

(2)给出pom.xml和application.yml的配置(只要你(1)中选的模块是和我一样的,那么pom.xml应该也是和我一样的)
pom.xml(feign-client)

<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>feign-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>feign-client</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml(feign-client):

server:
  port: 8080
spring:
  application:
    name: feign-client
eureka:
  client:
    service-url:
      # 注册到服务于该url的eurekaServer
      defaultZone: http://localhost:8761/eureka/

(3)在启动类上加上注解:@EnableDiscoveryClient

jeecg 微服务feign调用 eureka feign微服务间通信_ci_04

然后我们以相同的方式创建feign-server应用:
给出feign-server的application.yml配置文件(pom.xml就不给了,因为暂时不需要加东西)

server:
  port: 8081
spring:
  application:
    name: feign-server
eureka:
  client:
    service-url:
      # 注册到服务于该url的eurekaServer
      defaultZone: http://localhost:8761/eureka/

另外一定要给feign-server启动类加上注解:@EnableDiscoveryClient

至此,一个简单eureka服务端和两个客户端就创建好了,我们将这三个应用启动,然后在浏览器上输入:localhost:8761
看到如下画面就代表初步准备就已经弄好了:

jeecg 微服务feign调用 eureka feign微服务间通信_ci_05

 

接下来,我们配置并使用feign进行应用间的远程通信:
首先我们先理清思路,是feign-server要调用feign-client的服务,所以我们需要在feign-server应用里配置feign

在feign-server应用里配置feign:
(1)添加jar依赖:

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

(2)在启动类上加上注解:@EnableFeignClients,可以配置basePackage属性,指定feign客户端的包。(本应用没有指定)
 

 

接下来我们来编写业务类:

1、先写feign-client的接口:

目录结构:

jeecg 微服务feign调用 eureka feign微服务间通信_spring_06

 

ClientController类:

@Controller
@RequestMapping("/client")
public class ClientController {

    //返回字符串
    @GetMapping("/msg")
    @ResponseBody
    public String msg(){
        return "你调用了Client端的服务!";
    }

    //返回list,在list末尾添加“client”
    //必须使用Post方法,参数要加上@RequestBody
    @PostMapping("/list")
    @ResponseBody
    public List<String> list(@RequestBody List<String> list){
        list.add("client");
        return list;
    }
    
    //返回对象(为dog的name赋值)
    //必须使用Post方法,参数要加上@RequestBody
    @PostMapping("/dog")
    @ResponseBody
    public Dog setDogName(@RequestBody Dog dog){
        dog.setName("clientDog");
        return dog;
    }
}

 

Dog类:

public class Dog {
    private String name;
    
    //feign返回对象时,一定要添加无参构造方法,不然会报错:反序列化失败
    public Dog(){}

    public Dog(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

2、编写feign-server的业务类:

目录结构

jeecg 微服务feign调用 eureka feign微服务间通信_xml_07

 

AFeignClient接口(核心,通过该接口实现向客户端访问):

//@FeignClient里的name填写需要请求的客户端的name(注册在eureka上的name)
//即在application.yml里配置的spring.application.name
@FeignClient(name = "feign-client")
public interface AFeignClient {

    //url必须一样,方法名可以不同
    @GetMapping("/client/msg")
    String getMsgFromClient();

    @PostMapping("/client/list")
    List<String> getListFromClient(@RequestBody List<String> stringList);

    @PostMapping("/client/dog")
    Dog setDogName(@RequestBody Dog dog);
}

 

ServerController类:

@Controller
@RequestMapping("/server")
public class ServerController {

    //@Autowired 编译器可能会报红,但是依然能运行(大佬告诉我为啥...)
    //有人可能会说@EnableFeignClients注解可以配置basePackages属性指定feign-client
    //我这样做了,但是依然会报红
    //如果你的应用启动会报错,提示无法注入该bean,那么你可以配置下basePackages
    //例如:@EnableFeignClients(basePackages = "com.example.feignserver.client")
    @Autowired
    private AFeignClient aFeignClient;

    //从client端获取字符串
    @RequestMapping("/msg")
    public void msg(){
        String msg = aFeignClient.getMsgFromClient();
        System.out.println(msg);
    }

    //从client端获取处理后的list
    @RequestMapping("/list")
    public void list(){
        ArrayList<String> strList = new ArrayList<>();
        strList.add("server");
        List<String> listFromClient = aFeignClient.getListFromClient(strList);
        System.out.println(listFromClient);
    }

    //从client端获取处理的对象
    @RequestMapping("/dog")
    public void setDogName(){
        Dog dog = aFeignClient.setDogName(new Dog());
        System.out.println(dog.getName());
    }
}

Dog类和client端的是一样的,就不再给出了。

 

那么接下来该测试了:

(1)同时打开三个应用,在浏览器上访问localhost:8761,确认两个客户端都已经注册。

jeecg 微服务feign调用 eureka feign微服务间通信_jeecg 微服务feign调用_08

(2)测试server端的返回字符串接口,在浏览器上访问:localhost:8081/server/msg,feign-server的控制台打印出如下内容:   

jeecg 微服务feign调用 eureka feign微服务间通信_jeecg 微服务feign调用_09

(2)测试list接口,访问:localhost:8081/server/list,feign-server的控制台打印出如下内容:

jeecg 微服务feign调用 eureka feign微服务间通信_spring_10

(3)测试对象接口,访问:localhost:8081/server/dog,feign-server的控制台打印出如下内容:      

jeecg 微服务feign调用 eureka feign微服务间通信_ci_11

我们可以看见,feign-server应用通过feign向feign-client发送请求并接受了数据。