SpringCloud项目搭建(Feign客户端)调用

前言:之前写了篇关于SpringCloud项目搭建的文章,本想着后面真用到的时候可以直接参考学习,结果几个月后自己再搭建时发现自己都看不懂,此次将文章加以完善。力求小伙伴可以通过本篇文章能快速搭建起一个分布式项目

一、SpringCloud特点

目前公司开发项目使用分布式架构都是基于 dubbo+zookeeper的,两者优劣对比网上文章很多,怎么选择也得根据实际项目情况,比如:
SpringCloud是基于Springboot的,若一些较老的项目若使用SpringMVC则很难使用SpringCloud这一套来搭建分布式项目。
自己使用两个框架发现是SpringCloud搭建配置更简洁,项目结构也更简洁

SpringCloud是一套完整的分布式解决方案,所含组件主要包括:

1、Eureka:服务注册中心、服务治理中心(分布式服务核心组件)
2、zuul:加在整个微服务最前沿的防火墙和代理器,隐藏微服务结点IP端口信息,加强安全保护
3、Ribbon:客户端负载均衡器,用于调用集群
4、Feign客户端:声明示远程服务调用
5、Config:分布式配置中心

二、SpringCloud项目搭建
分布式项目涉及到项目较多,且基本所有项目都公用大部分依赖,因此采用父子类工程。可减少许多重复添加依赖的情况(父子功能工程搭建此处简略描述)
1、搭建Parent父工程

快速创建maven工程,注意packaging 不要选择jar,选择pom,也可直接修改pom.xml

<packaging>pom</packaging>

其他folder或者sourceFolder都可以删除,只留下pom.xml文件
2、配置SpringCloud所需依赖,主要为以下子项目提供,父类有的依赖子类若需要也可不必再配置
贴上完整父工程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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.landlord.canbar</groupId>
    <artifactId>canbar-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>canbar-parent</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
<!-- SpringBoot 依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
<!--        Eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
<!--        引用feign客户端端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
<!--        项目热部署  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
         <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
  <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>
    <modules>
        <module>canbar-access-service</module>
        <module>canbar-eureka</module>
    <module>canbar-user-service</module>
  </modules>
</project>
2、新建注册中心--eureka项目

maven依赖已在父工程,东西不多,直接上配置和和代码:

启动类:
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication 
{
    public static void main( String[] args )
    {
        SpringApplication.run(EurekaApplication.class, args);
    }
}
applicayion.yml配置:
#端口号
server:
  port: 8760
eureka:
  instance:
    hostname: localhost
  client:
    # eureka.client.registerWithEureka :表示是否将自己注册到Eureka Server,默认为true。
    # 由于当前这个应用就是Eureka Server,故而设为false
    register-with-eureka: false
    # eureka.client.fetchRegistry :表示是否从Eureka Server获取注册信息,默认为true。因为这是一个单点的Eureka Server,
    # 不需要同步其他的Eureka Server节点的数据,故而设为false。
    fetch-registry: false
    service-url:
      # eureka.client.serviceUrl.defaultZone :设置与Eureka Server交互的地址,
      #查询服务和注册服务都需要依赖这个地址。默认是
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
spring:
  application:
    name: canbar-eureka

启动项目:访问http://localhost:8760/

Eureka启动成功页面,暂无服务注册

3、搭建子项目①-服务提供者,虽然各子项目之间可项目调用,故每个子项目既是服务提供者,也是服务消费者,但此处便于描述,将项目①定位为服务提供者,

变化不大,依旧是依赖在父工程,直接贴代码:

启动类:
@SpringBootApplication
@EnableEurekaServer
public class AccessApplication 
{
    public static void main( String[] args )
    {
       SpringApplication.run(AccessApplication.class, args);
    }
}
application.yml,配置文件中服务name需注意,因为服务时已该名字注册到注册中心的
server:
  port: 8762
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8760/eureka/
      
ribbon:
  eureka:
    enabled: true
      
spring:
  application:
    name: canbar-access
Controller类:
@RestController
public class ConsumerController {
    @RequestMapping("/getAccess")
    public String getAccess(String param){
        
        return "get access success!"+ param;
    }
}

服务提供者项目搭建完成,可直接启动项。
访问:http://localhost:8762/getAccess?param=create-provider-success

直接访问结果

或者接下来等待消费者调用

4、搭建子项目②-服务消费者

相对于服务提供者和eureka,因此处使用声明式调用(feign客户端,方便简洁,用起来爽),多了Feign的依赖,但已在父工程中引用,故pom也可不动。
另:还可使用使用restTemplate方式调用,因我没用,故暂不写

启动类:
@SpringBootApplication
@EnableEurekaServer
// 使用Feign客户端调用
@EnableFeignClients
public class UserApplication 
{
    public static void main( String[] args )
    {
        SpringApplication.run(UserApplication.class, args);
    }
}

Feign客户端:

// 括号中参数为被调用这服务注册名字,不能错
@FeignClient("canbar-access")
public interface AccessFeignService {
//对应被调用服务的mapping
    @RequestMapping("/getAccess")
//方法名需与被调用服务对应mapping的方法相同,此处的getAccess
//@RequestParam("param")对应参数应与服务提供者接受参数一致,要不参数会传递失败
    String getAccess(@RequestParam("param")String param);
}
controller类:
@Controller
public class UserloginController {
//注入  feign客户端
    @Autowired
    AccessFeignService accessFeignService;
    @RequestMapping("/getAccess")
    @ResponseBody
    public String  getAccess(String param){
        String str = accessFeignService.getAccess(param);
        return "this is customer,test get remote msg:"+str;
    }
}
application.yml
server:
  port: 8763
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8760/eureka/

ribbon:
  eureka:
    enabled: true
      
spring:
  application:
    name: canbar-user

消费者项目搭建完成:
访问:http://localhost:8763/getAccess?param=Remote-call-successful

远程调用结果

注意此时的Eureka:
Eureka服务管理
至此,一个简易分布式框架搭建完成。接下来我们一起体验SpringCloud的其他强大功能。