06、SpringCloud之feign的工程化实例(分布式工程)

举报
长路 发表于 2022/11/28 20:08:04 2022/11/28
【摘要】 Gitee仓库、Github仓库博客目录索引(持续更新)动力节点最新SpringCloud视频教程|最适合自学的springcloud+springcloudAlibabaPS本章节中部分图片是直接引用学习课程课件,如有侵权,请联系删除。项目模块展示注册中心使用之前eureka案例中的即可接着按照2.1中的项目架构图来进行搭建模块,分别是api模块、doamin模块、order服务模块以及user

@[toc]

前言

本节配套案例代码:Gitee仓库Github仓库

所有博客文件目录索引:博客目录索引(持续更新)

学习视频:动力节点最新SpringCloud视频教程|最适合自学的springcloud+springcloudAlibaba

PS:本章节中部分图片是直接引用学习课程课件,如有侵权,请联系删除。

一、了解项目模块的演进

1.1、单体项目

单体项目

单模块:所有的功能模块都写在一个项目中,然后单独部署。

image-20220718140529965

多模块聚合:将一个项目进行拆分为多模块管理

image-20220718140622301

1.2、分布式项目

分布式项目

分布式聚合项目(不太推荐):整个项目根据提供的不同服务来拆分,不同服务可以单独作为一个微服务对象提供访问,服务与服务之间需要相互依赖。

问题:例如下面的car-service服务中的service来进行远程调用需要引入rent-service的domain模块依赖,这就会导致若是有大量不同的服务后造成不好梳理的问题。

image-20220718140731601

优化聚合项目方案

方案一(个人觉得不太行):将原本的多个mapper、service以及web进行合并为一个xx-core模块,xx-domain单独作为一个模块,然后其他服务想要进行调用那么引入对应的xx-domain依赖。

问题:可能单独的一个服务项目因为这样依赖就需要在项目启动过程时多编译几百个类,会让启动速度略慢些。

image-20220718141025597

方案二:单独构建一个api模块,然后多个服务去依赖该模块,这种方案当我服务需要创建新的实体时,直接添加到该api模块中。

image-20220718141410157


二、基于feign的工程化项目创建

2.1、案例目标及项目架构图

api模块依赖domain模块,然后其他服务依赖该api接口模块。

  • domain:实体类。
  • api:放置公共接口,例如feign接口。

image-20220718141832411

2.2、实战—项目模块搭建

2.2.1、各个模块介绍及父模块pom.xml

项目模块展示

注册中心:使用之前eureka案例中的即可

image-20220718150423235

接着按照2.1中的项目架构图来进行搭建模块,分别是:api模块、doamin模块、order服务模块以及user服务模块

依赖关系如下:

  • api模块依赖domain模块。
    • domain:添加对应的实体类。
    • api:主要是编写对应的远程调用api接口以及断路器实现类。
  • order、user服务模块依赖api模块。
    • order服务主要是对外提供服务。
    • user服务中某个接口会进行调用order服务。

image-20220718150444317

所有的包名统一前缀为com.changlu。

对于04-feign-project父模块的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">
    <!--  父模块依赖  -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <!-- 创建好子模块之后,就会自动添加packaging以及modules管理   -->
    <groupId>com.changlu</groupId>
    <artifactId>04-feign-project</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>domain-project</module>
        <module>common-api</module>
        <module>user-center</module>
        <module>order-center</module>
    </modules>

    <!--全局版本控制-->
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
    </properties>

    <!--  全局依赖的模块  -->
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </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>-->

<!--    </build>-->

</project>

2.2.2、domain-project模块

说明:该模块主要放置一些实体类。

image-20220718150845829

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">
    <parent>
        <artifactId>04-feign-project</artifactId>
        <groupId>com.changlu</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>domain-project</artifactId>

</project>

Order.java实体类:

package com.changlu.domain;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Description:
 * @Author: changlu
 * @Date: 2:30 PM
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Order {

    private Integer orderId;
    private String orderName;
    private Double price;

}

2.2.3、common-api模块

说明:这个模块主要放一些公共的api接口,例如feign接口以及hystrix断路器接口。

image-20220718151106230

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">
    <parent>
        <artifactId>04-feign-project</artifactId>
        <groupId>com.changlu</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>common-api</artifactId>

    <dependencies>
        <!--    依赖domain    -->
        <dependency>
            <groupId>com.changlu</groupId>
            <artifactId>domain-project</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

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

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


</project>

com/changlu/feign/UserOrderFeign.java:feign接口规范

package com.changlu.feign;

import com.changlu.domain.Order;
import com.changlu.feign.hystrix.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @Description:
 * @Author: changlu
 * @Date: 2:39 PM
 */
@FeignClient(value = "order-service", fallback = UserOrderFeignHystrix.class)
public interface UserOrderFeign {

    @GetMapping("/order/{id}")
    Order getOrderById(@PathVariable("id")Integer id);

}

com.changlu.feign.hystrix.UserOrderFeignHystrix:对应上面feign的断路器

package com.changlu.feign.hystrix;

import com.changlu.domain.Order;
import com.changlu.feign.UserOrderFeign;
import org.springframework.stereotype.Component;

/**
 * @Description:
 * @Author: changlu
 * @Date: 2:43 PM
 */
@Component
public class UserOrderFeignHystrix implements UserOrderFeign {
    @Override
    public Order getOrderById(Integer id) {
        return null;
    }
}

2.2.4、order-center服务模块

说明:该模块主要是对外提供订单服务。

image-20220718151314305

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">
    <parent>
        <artifactId>04-feign-project</artifactId>
        <groupId>com.changlu</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order-center</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--    引入api依赖    -->
        <dependency>
            <groupId>com.changlu</groupId>
            <artifactId>common-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <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>
    </dependencies>


</project>

配置文件application.yaml:

server:
  port: 8081
spring:
  application:
    name: order-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

①添加启动器注解,开启服务注册

package com.changlu;

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

/**
 * @Description:
 * @Author: changlu
 * @Date: 2:36 PM
 */
@SpringBootApplication
@EnableEurekaClient
public class OrderServiceApplication {

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

②创建订单控制器:com.changlu.controller.OrderController

package com.changlu.controller;

import com.changlu.domain.Order;
import com.changlu.feign.UserOrderFeign;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description:
 * @Author: changlu
 * @Date: 2:38 PM
 */
@RestController
public class OrderController implements UserOrderFeign {

        @Override
        public Order getOrderById(Integer id) {
            Order order = Order.builder()
                    .orderId(id)
                    .price(100.0)
                    .orderName("牛奶布丁").build();
            return order;
        }


}

2.2.5、user-center服务模块

说明:该用户服务主要是对外提供用户服务,在提供用户服务过程中会进行调用订单服务,其中就涉及到了openfeign组件以及hystrix断路器组件(需要手动开启)。

image-20220718151603041

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">
    <parent>
        <artifactId>04-feign-project</artifactId>
        <groupId>com.changlu</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user-center</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--    引入api依赖    -->
        <dependency>
            <groupId>com.changlu</groupId>
            <artifactId>common-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <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>
    </dependencies>


</project>

配置文件application.yaml:

server:
  port: 8082
spring:
  application:
    name: user-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

# 开启熔断
feign:
  hystrix:
    enabled: true

①创建启动器,添加服务注册以及feign包扫描

package com.changlu;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @Description:
 * @Author: changlu
 * @Date: 2:52 PM
 */
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.changlu.feign")
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

②创建用户控制器:com.changlu.controller.UserController

package com.changlu.controller;

import com.changlu.domain.Order;
import com.changlu.feign.UserOrderFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description:
 * @Author: changlu
 * @Date: 2:53 PM
 */
@RestController
public class UserController {

    @Autowired
    private UserOrderFeign feign;

    @GetMapping("/user/order/{userId}")
    public Order getOrderByUserId(@PathVariable("userId")Integer userId) {
        //根据用户id获取到订单id
        Integer id = 1111;
        Order order = feign.getOrderById(id);
        return order;
    }

}

至此,我们的项目模块搭建完成。

2.3、项目模块测试

我们启动注册中心、订单服务以及用户服务:

image-20220718152211560

接着我们来访问用户服务:http://localhost:8082/user/order/123

image-20220718152259461

接着我们将订单服务关闭,再此访问查看下:

image-20220718152338166

成功,当订单服务不可用时,即可返回对应断路器的内容。


参考资料

[1]. 动力结点springcloud-feign工程案例

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。