SpringBoot + SpringCloud Feign 多模块 框架搭建案例

2019-11-19 10:04:54 | 编辑

看了别人的案例,发现spring cloud 接口调用都是用 http地址来调用,即使使用RestTemplate,我也觉得太傻,所以我决定使用Feign模式来搭建spring boot+ spring cloud微服务集群。而且实现了使用类传参数。另外还使用类接口编程的模式。下面来用最简单的代码,搭建最完善的框架。

1.为什么要用Feign模式

,我不想每调用一个接口,要拼url那么傻的方式。

面向对象,我希望像调用本地一个方法一样,我不想管地址,参数怎么组成拼接什么的,我只管调用

 

Feign是一个声明式WebService客户端
Spring Cloud 的声明式调用, 可以做到使用 HTTP 请求远程服务时能就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。
它像 Dubbo 一样,consumer 直接调用接口方法调用 provider,而不需要通过常规的Http Client 构造请求再解析返回数据。
它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

 

2.项目结构

demo: 父项目

eureka: spring cloud 注册中心

consumer:消费者调用接口

producer:生产者 提供接口实现

commonApi:定义要暴露的接口,consumer只需要引用commonApi,注入接口就能调用spring cloud 提供的接口。

 

3.demo父项目配置

<?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 https://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.2.0.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>net.itxw.demo</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <packaging>pom</packaging>

    <modules>
        <module>eureka</module>
        <module>commonApi</module>
        <module>consumer</module>
        <module>producer</module>
    </modules>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

	<!--引入spring cloud版本-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>


        </dependencies>
    </dependencyManagement>
	<!--spring cloud版本很多,和spring boot 匹配也不同,所以指定官方仓库-->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

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

</project>

公用包都在父项目pom已经引入

4.eureka注册中心搭建

4.1 pom

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>net.itxw.demo</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>net.itxw.demo</groupId>
    <artifactId>eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    
    <packaging>jar</packaging>

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

</project>

 

4.2启动类

package net.itxw.demo.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

}

 

4.3 application.properties

spring.application.name=eureka-server

server.port=8000

eureka.client.service-url.defaultZone=http://127.0.0.1:8000/eureka/

#表示是否将自己注册在EurekaServer上,默认为true。由于当前应用就是EurekaServer,所以置为false
eureka.client.register-with-eureka=false
#表示表示是否从EurekaServer获取注册信息,默认为true。单节点不需要同步其他的EurekaServer节点的数据
eureka.client.fetch-registry=false

 

4.4 启动eureka注册中心

http://localhost:8000/

 

5.commonApi 编写接口

5.1接口

package net.itxw.demo.commonApi.api;

import net.itxw.demo.dto.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

/**
 * feign接口 name对应 服务提供方的  spring.application.name
 * @Author: houyong
 * @Date: 2019/11/1
 */
@FeignClient(name= "producer")
public interface IUser {

    /**
     * 获取学生信息
     * @param user
     */
    @RequestMapping("/getUser")
    String getUser(@RequestBody User user);
	

}

 

5.2 User 类

注意使用了lombok,需要使用lombok插件

package net.itxw.demo.commonApi.dto;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;

/**
 * 学生信息
 * @Author: houyong
 * @Date: 2019/11/1
 */
@Getter
@Setter
public class User implements Serializable {

    private String id;
    private String name;

    private String schoolId;
    private String schoolName;
   
    private String classId;
    private String className;


}

 

5.3 pom

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>net.itxw.demo</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>net.itxw.demo</groupId>
    <artifactId>commonApi</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<!--不需要使用spring boot打启动包,否则引用失败,打普通jar包就可以-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

6.producer项目 (实现接口)

6.1 pom (引入 commonApi项目)

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>net.itxw.demo</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>net.itxw.demo</groupId>
    <artifactId>producer</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <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>

        <dependency>
            <groupId>net.itxw.demo</groupId>
            <artifactId>commonApi</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>


</project>

 

6.2 实现接口IUser

package net.itxw.demo.producer.service.impl;


import net.itxw.demo.commonApi.api.IUser;
import net.itxw.demo.commonApi.dto.User;


/**
 * RestController表示这个实现是要暴露接口的
 * @Author: houyong
 * @Date: 2019/11/4
 */
@Slf4j
@RestController
public class UserImpl implements IUser {

    @Override
    public String getUser(User user){
		log.warn("我producer被其他服务调用了");
        return "我是producer,您的名字是:"+user.getName();
    }


}

6.3 application.properties

spring.application.name=producer
server.port=8001

#允许多个同名的@FeignClient 同时存在
spring.main.allow-bean-definition-overriding=true

#调用接口超时设置
ribbon.ReadTimeout=60000
ribbon.ConnectTimeout=60000
ribbon.MaxAutoRetries=0
ribbon.MaxAutoRetriesNextServer=1


eureka.client.service-url.defaultZone=http://127.0.0.1:8000/eureka/

 

6.4 启动类

package net.itxw.demo.producer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
//能扫描到整个项目的Feign注解
@EnableFeignClients(basePackages = "net.itxw.demo")
public class ProducerApplication {

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

}

 

6.5 启动producer

启动成功后 在 eureka界面下的 Instances currently registered with Eureka 可以看到producer项目,已经注册进来

 

7.consumer项目 (调用接口)

7.1 pom 引用commonApi

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>net.itxw.demo</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>net.itxw.demo</groupId>
    <artifactId>consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <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>

        <dependency>
            <groupId>net.itxw.demo</groupId>
            <artifactId>commonApi</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>


</project>

 

7.2 controller调用IUser接口

package net.itxw.demo.consumer.action;

import net.itxw.demo.commonApi.api.IUser;
import net.itxw.demo.commonApi.dto.User;


@RestController
public class TestController {

    @Autowired
    private IUser iuser;

    @RequestMapping("/test")
    public String test() {
		User user=new User();
		user.setName("IT学问网");
        return iuser.getUser(user);
    }
}

 

7.3 启动类

package net.itxw.demo.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
//能扫描到整个项目的Feign注解
@EnableFeignClients(basePackages = "net.itxw.demo")
public class ConsumerApplication {

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

}

 

7.4 application.properties

spring.application.name=consumer
server.port=8002

#允许多个同名的@FeignClient 同时存在
spring.main.allow-bean-definition-overriding=true

#调用接口超时设置
ribbon.ReadTimeout=60000
ribbon.ConnectTimeout=60000
ribbon.MaxAutoRetries=0
ribbon.MaxAutoRetriesNextServer=1


eureka.client.service-url.defaultZone=http://127.0.0.1:8000/eureka/

 

7.5 启动consumer

启动成功后 在 eureka界面下的 Instances currently registered with Eureka 可以看到consumer项目,已经注册进来

 

8.测试

浏览器访问:localhost:8002/test

我使用的postman:

 

OK,很顺利,spring boot + spring cloud + Feign+接口编程模式 的框架搭建成功!

 

登录后即可回复 登录 | 注册
    
关注编程学问公众号