SpringCloud项目搭建实例

发布于 2022-4-27 16:50
浏览
0收藏

作者 | 星空XXL
来源 | 今日头条

SpringCloud介绍

SpringCloud是基于SpringBoot提供的一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件。

项目说明

以搭建一个部门管理系统为例,记录使用SpringCloud搭建项目的过程,使用的组件包括 Eureka、Ribbon、Fegin、Hystrix、Zuul等。

组件介绍(纯手工制作^-^)

Eureka 服务注册与发现SpringCloud项目搭建实例-开源基础软件社区

Ribbon和Feign负载均衡SpringCloud项目搭建实例-开源基础软件社区

Hystrix服务熔断

  • 服务熔断

某个服务故障或者异常,类似现实世界中的“保险丝”,当某个异常条件被触发,直接熔断整个服务,而不是一直等到此服务超时。

  • 服务降级

就是当某个服务熔断后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值,这样做,虽然服务水平下降了,但好歹可用,比直接挂掉要强。SpringCloud项目搭建实例-开源基础软件社区

Zuul网关SpringCloud项目搭建实例-开源基础软件社区

搭建父工程

目录结构

deptmanagecloud 
└── pom.xml

pom.xml

内容如下(此时内容只有最基础的部分,还没包括其它jar):

<?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.omygod.springcloud</groupId>
    <artifactId>deptmanagecloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--重要,父工程打包方式为POM-->
    <packaging>pom</packaging>

    <properties>
        <!--源文件编码-->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--JDK版本-->
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!--SpringBoot版本-->
        <springboot.version>2.2.6.RELEASE</springboot.version>
        <!--SpringCloud版本-->
        <springcloud.version>Hoxton.SR3</springcloud.version>
    </properties>

    <!--配置阿里云中心仓库-->
    <repositories>
        <repository>
            <id>maven-aliyun</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>always</updatePolicy>
                <checksumPolicy>fail</checksumPolicy>
            </snapshots>
        </repository>
    </repositories>

    <!--项目版本号定义-->
    <dependencyManagement>
        <dependencies>
            <!--引入springcloud依赖版本管理-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${springcloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--引入springboot依赖版本管理-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

搭建Eureka Server工程模块

目录结构

deptmanagecloud
├── deptmanage-eureka-7001
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── com
│       │   │       └── omygod
│       │   │           └── springcloud
│       │   │               └── deptmanagecloud
│       │   │                   └── EurekaServer7001.java
│       │   └── resources
│       │       └── application.yml
│       └── test
│           └── java
└── 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">
    <parent>
        <artifactId>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
	<!--当前模块的名称,可自定义-->
    <artifactId>deptmanage-eureka-7001</artifactId>

    <!--只需要引入eureka-server依赖即可-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
    
     <!--spring-boot-maven-plugin插件作用,当运行“mvn package”进行打包时,会打包成一个可以直接运行的 JAR 文件,使用“Java -jar”命令就可以直接运行-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

# 单机版配置
server:
  port: 7001
eureka:
  instance:
    hostname: localhost  # eureka服务端实例名称
  server:
    enable-self-preservation: true  # 自我保护机制
  client:
    register-with-eureka: false  # false表示不向注册中心注册自己
    fetch-registry: false  # false表示自己就是注册中心,不需要去检索服务
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  # 设置与eureka server 交互的地址查询服务和注册服务都要依赖这个地址

添加启动类

package com.omygod.springcloud.deptmanagecloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer //启动eureka服务端,接受客户端的注册和发现
public class EurekaServer7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer7001.class,args);
    }
}

测试单机版配置

1.启动工程

2.访问 http://localhost:7001

3.如出现如下页面,则启动成功SpringCloud项目搭建实例-开源基础软件社区

搭建Eureka Server集群

在本地的`hosts`文件中添加如下配置

127.0.0.1   eureka7001.hosts
127.0.0.1   eureka7002.hosts
127.0.0.1   eureka7003.hosts
# 具体多少个视情况而定

复制单机版Eureka Server工程(具体多少个视情况而定,这里复2个)

复制后的目录结构如下:

deptmanagecloud
├── deptmanage-eureka-7001
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── com
│       │   │       └── omygod
│       │   │           └── springcloud
│       │   │               └── deptmanagecloud
│       │   │                   └── EurekaServer7001.java
│       │   └── resources
│       │       └── application.yml
│       └── test
│           └── java
├── deptmanage-eureka-7002
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── com
│       │   │       └── omygod
│       │   │           └── springcloud
│       │   │               └── deptmanagecloud
│       │   │                   └── EurekaServer7002.java
│       │   └── resources
│       │       └── application.yml
│       └── test
│           └── java
├── deptmanage-eureka-7003
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── com
│       │   │       └── omygod
│       │   │           └── springcloud
│       │   │               └── deptmanagecloud
│       │   │                   └── EurekaServer7003.java
│       │   └── resources
│       │       └── application.yml
│       └── test
│           └── java
└── 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">
    <parent>
        <artifactId>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>更改的模块名称</artifactId>

    <!--只需要引入eureka-server依赖即可-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>
    <!--spring-boot-maven-plugin插件作用,当运行“mvn package”进行打包时,会打包成一个可以直接运行的 JAR 文件,使用“Java -jar”命令就可以直接运行-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

复制修改启动类,只有类名发生变化

package com.omygod.springcloud.deptmanagecloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer //启动eureka服务端,接受客户端的注册和发现
public class 对应启动类名 {
    public static void main(String[] args) {
        SpringApplication.run(对应启动类名.class,args);
    }
}

主要修改的是application.yml配置文件的内容

# eureka7001.hosts
# 集群配置
server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.hosts  # eureka服务端实例名称
#    server:
#      enable-self-preservation: true  # 自我保护机制
  client:
    register-with-eureka: false  # false表示不向注册中心注册自己
    fetch-registry: false  # false表示自己就是注册中心,不需要去检索服务
    service-url:
      # 集群使用的是其它eureka server 的地址 
      # 设置与eureka server 交互的地址查询服务和注册服务都要依赖这个地址
      defaultZone: http://eureka7002.hosts:7002/eureka/,http://eureka7003.hosts:7003/eureka/
# eureka7002.hosts
# 集群配置
server:
  port: 7002
eureka:
  instance:
    hostname: eureka7002.hosts  # eureka服务端实例名称
  #    server:
  #      enable-self-preservation: true  # 自我保护机制
  client:
    register-with-eureka: false  # false表示不向注册中心注册自己
    fetch-registry: false  # false表示自己就是注册中心,不需要去检索服务
    service-url:
      # 集群使用的是其它eureka server 的地址 
      # 设置与eureka server 交互的地址查询服务和注册服务都要依赖这个地址
      defaultZone: http://eureka7001.hosts:7001/eureka/,http://eureka7003.hosts:7003/eureka/
# eureka7003.hosts
# 集群配置
server:
  port: 7003
eureka:
  instance:
    hostname: eureka7003.hosts  # eureka服务端实例名称
  #    server:
  #      enable-self-preservation: true  # 自我保护机制
  client:
    register-with-eureka: false  # false表示不向注册中心注册自己
    fetch-registry: false  # false表示自己就是注册中心,不需要去检索服务
    service-url:
      # 集群使用的是其它eureka server 的地址 
      # 设置与eureka server 交互的地址查询服务和注册服务都要依赖这个地址
      defaultZone: http://eureka7002.hosts:7002/eureka/,http://eureka7001.hosts:7001/eureka/

测试集群

1.启动三个eureka server实例

2.访问

http://eureka7001.hosts:7001 ,http://eureka7002.hosts:7002 ,http://eureka7003.hosts:7003 ,出现如上图所示页面,则集群搭建成功SpringCloud项目搭建实例-开源基础软件社区

此时的父工程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>

    <groupId>com.omygod.springcloud</groupId>
    <artifactId>deptmanagecloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>deptmanage-eureka-7001</module>
        <module>deptmanage-eureka-7002</module>
        <module>deptmanage-eureka-7003</module>
    </modules>
    <!--重要,父工程打包方式为POM-->
    <packaging>pom</packaging>

    略
   
</project>

创建部门表(dept)

-- 表的结构 `dept`
CREATE TABLE `dept` (
  `deptno` int(11) NOT NULL,
  `deptname` varchar(50) NOT NULL,
  `dbsource` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `dept` (`deptno`, `deptname`, `dbsource`) VALUES
(2, '财务部', 'deptmanage01'),
(3, '行政部', 'deptmanage01'),
(4, '研发部', 'deptmanage01');

ALTER TABLE `dept` ADD PRIMARY KEY (`deptno`);

ALTER TABLE `dept` MODIFY `deptno` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0;

搭建部门管理系统模块

父工程

eureka 模块

通用API模块

部门服务提供者模块

部门服务消费者模块

搭建通用API模块

目录结构

deptmanagecloud
├── deptmanagecloud-api
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   └── resources
│       └── test
│           └── java
└── pom.xml

pom.xml

因项目需要用到数据库操作,所以添加了mybatis plus插件的注解jar包,相关版本号已在父工程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>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>deptmanagecloud-api</artifactId>

    <dependencies>
        <!--引入lombok插件,简化开发-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--mybatis-plus-annotation 注解包-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-annotation</artifactId>
        </dependency>
    </dependencies>

</project>

部门服务提供者模块

目录结构

deptmanagecloud/
├── deptmanagecloud-api
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   └── resources
│       └── test
│           └── java
├── deptmanagecloud-provider-8001
│   ├── pom.xml
│   ├── src
│   │   ├── main
│   │   │   ├── java
│   │   │   │   └── com
│   │   │   │       └── omygod
│   │   │   │           └── springcloud
│   │   │   │               ├── deptmanagecloud
│   │   │   │               │   └── provider
│   │   │   │               │       ├── controller
│   │   │   │               │       │   └── DeptController.java
│   │   │   │               │       ├── entity
│   │   │   │               │       │   └── Dept.java
│   │   │   │               │       ├── mapper
│   │   │   │               │       │   └── DeptMapper.java
│   │   │   │               │       └── service
│   │   │   │               │           ├── IDeptService.java
│   │   │   │               │           └── impl
│   │   │   │               │               └── DeptServiceImpl.java
│   │   │   │               └── mybatisplus
│   │   │   │                   └── generator
│   │   │   │                       └── MysqlGenerator.java
│   │   │   └── resources
│   │   │       ├── application.yml
│   │   │       └── mapper
│   │   │           └── provider
│   │   │               └── DeptMapper.xml
│   │   └── test
│   │       └── java
└── 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">
    <parent>
        <artifactId>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>deptmanagecloud-provider-8001</artifactId>

    <dependencies>
        <!--引入Springboot启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--引入Springboot web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入Eureka 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        
        <!--根据业务,引入模块必要的jar-->
        
        <!--引入自定义的jar-->
        <dependency>
            <groupId>com.omygod.springcloud</groupId>
            <artifactId>deptmanagecloud-api</artifactId>
            <version>${project.version}</version>
        </dependency>
        
        <!--引入数据库连接相关jar包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>
        <!--引入 MyBatis-Plus 之后请不要再次引入 MyBatis 以及 MyBatis-Spring,以避免因版本差异导致的问题-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!--代码生成器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
        </dependency>
        <!--代码生成器模板-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.2</version>
        </dependency>
    </dependencies>
</project>

application.yml

server:
  port: 8001

spring:
  application:
    name: deptmanagecloud-provider
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/deptmanage01
    username: root
    password: 12345678
    dbcp2:
      min-idle: 5
      initial-size: 5
      max-total: 5
      max-wait-millis: 200

eureka:
  client:  # 客户端注册进Eureka服务列表内
    service-url:
      defaultZone: http://eureka7001.hosts:7001/eureka/,http://eureka7002.hosts:7002/eureka/,http://eureka7003.hosts:7003/eureka/  # 如果是集群环境,Eureka的地址使用‘,’隔开

mybatis-plus:
  mapper-locations: classpath*:/mapper/*.xml
  type-aliases-package: com.omygod.springcloud.entity
  type-aliases-super-type: java.lang.Object

使用代码生成器

package com.omygod.springcloud.mybatisplus.generator;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;

import java.util.ArrayList;
import java.util.List;

/**
 * MySQL 自动生成数据表 代码生成器
 */
public class MysqlGenerator {
    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir")+"/deptmanagecloud-provider-8001";
        gc.setOutputDir(projectPath + "/src/main/java/");
        gc.setAuthor("omygod");
        gc.setOpen(false);
        // gc.setSwagger2(true); 实体属性 Swagger2 注解
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/deptmanage01?useUnicode=true&useSSL=false&characterEncoding=utf8");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("12345678");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName("provider");
        pc.setParent("com.omygod.springcloud.deptmanagecloud");
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        //String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        /*
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判断自定义文件夹是否需要创建
                checkDir("调用默认方法创建的目录");
                return false;
            }
        });
        */
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定义输出模板
        //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        // templateConfig.setEntity("templates/entity2.java");
        // templateConfig.setService();
        // templateConfig.setController();

        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new VelocityTemplateEngine());
        mpg.execute();
    }
}

新建主启动类

package com.omygod.springcloud;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
// 启动Eureka客户端,注册服务
@EnableEurekaClient
// Mybatis plus 配置包扫描路径
@MapperScan("com.omygod.springcloud.deptmanagecloud.*.mapper")
public class Provider8001 {
    public static void main(String[] args) {
        SpringApplication.run(Provider8001.class,args);
    }

    /**
     * 配置 mybatis plus 分页插件,可新建一个配置类
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}

在controller中添加方法

package com.omygod.springcloud.deptmanagecloud.provider.controller;

import com.omygod.springcloud.deptmanagecloud.provider.entity.Dept;
import com.omygod.springcloud.deptmanagecloud.provider.service.IDeptService;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/provider/dept")
public class DeptController {

    @Autowired
    IDeptService deptService;

    @GetMapping("/get/{id}")
    public Dept getDept(@PathVariable(value = "id") Integer id){
        return deptService.getById(id);
    }

    @GetMapping("/list")
    public List<Dept> getDeptList(){
        return deptService.list();
    }
}

测试

访问 `

http://localhost:8001/provider/dept/list` ,返回如下结果表示成功:

[
    {
        "deptno": 2,
        "deptname": "财务部",
        "dbsource": "deptmanage01"
    },
    {
        "deptno": 3,
        "deptname": "行政部",
        "dbsource": "deptmanage01"
    },
    {
        "deptno": 4,
        "deptname": "研发部",
        "dbsource": "deptmanage01"
    }
]

查看eureka server中是否存在名为 deptmanagecloud-provider 的服务

搭建服务提供者集群

复制 服务提供者 模块(数量视具体情况而定),依次修改 主启动类类名,application.yml文件端口号,pom.xml文件模块名称,最后在父工程中添加复制的模块

# 模块名称
deptmanagecloud-provider-8001
deptmanagecloud-provider-8002
deptmanagecloud-provider-8003
# 主启动类名称
Provider8001
Provider8002
Provider8003
# 端口号
8001
8002
8003

复制数据库,插入相应数据,修改数据库链接

jdbc:mysql://localhost:3306/deptmanage01   deptmanagecloud-provider-8001
jdbc:mysql://localhost:3306/deptmanage02   deptmanagecloud-provider-8002
jdbc:mysql://localhost:3306/deptmanage03   deptmanagecloud-provider-8003

[
    {
        "deptno": 2,
        "deptname": "财务部",
        "dbsource": "对应数据库名称"
    },
    {
        "deptno": 3,
        "deptname": "行政部",
        "dbsource": "对应数据库名称"
    },
    {
        "deptno": 4,
        "deptname": "研发部",
        "dbsource": "对应数据库名称"
    }
]

目录结构如下

deptmanagecloud
├── deptmanagecloud-provider-8001
│   ├── pom.xml
│   ├── src
│   │   ├── main
│   │   │   ├── java
│   │   │   │   └── com
│   │   │   │       └── omygod
│   │   │   │           └── springcloud
│   │   │   │               ├── deptmanagecloud
│   │   │   │               │   └── provider
│   │   │   │               │       ├── controller
│   │   │   │               │       │   └── DeptController.java
│   │   │   │               │       ├── mapper
│   │   │   │               │       │   └── DeptMapper.java
│   │   │   │               │       └── service
│   │   │   │               │           ├── IDeptService.java
│   │   │   │               │           └── impl
│   │   │   │               │               └── DeptServiceImpl.java
│   │   │   │               ├── mybatisplus
│   │   │   │               │   └── generator
│   │   │   │               │       └── MysqlGenerator.java
│   │   │   │               └── Provider8001.java
│   │   │   └── resources
│   │   │       ├── application.yml
│   │   │       └── mapper
│   │   │           └── provider
│   │   │               └── DeptMapper.xml
│   │   └── test
│   │       └── java
├── deptmanagecloud-provider-8002
│   ├── pom.xml
│   ├── src
│   │   ├── main
│   │   │   ├── java
│   │   │   │   └── com
│   │   │   │       └── omygod
│   │   │   │           └── springcloud
│   │   │   │               ├── deptmanagecloud
│   │   │   │               │   └── provider
│   │   │   │               │       ├── controller
│   │   │   │               │       │   └── DeptController.java
│   │   │   │               │       ├── mapper
│   │   │   │               │       │   └── DeptMapper.java
│   │   │   │               │       └── service
│   │   │   │               │           ├── IDeptService.java
│   │   │   │               │           └── impl
│   │   │   │               │               └── DeptServiceImpl.java
│   │   │   │               ├── mybatisplus
│   │   │   │               │   └── generator
│   │   │   │               │       └── MysqlGenerator.java
│   │   │   │               └── Provider8002.java
│   │   │   └── resources
│   │   │       ├── application.yml
│   │   │       └── mapper
│   │   │           └── provider
│   │   │               └── DeptMapper.xml
│   │   └── test
│   │       └── java
├── deptmanagecloud-provider-8003
│   ├── pom.xml
│   ├── src
│   │   ├── main
│   │   │   ├── java
│   │   │   │   └── com
│   │   │   │       └── omygod
│   │   │   │           └── springcloud
│   │   │   │               ├── deptmanagecloud
│   │   │   │               │   └── provider
│   │   │   │               │       ├── controller
│   │   │   │               │       │   └── DeptController.java
│   │   │   │               │       ├── mapper
│   │   │   │               │       │   └── DeptMapper.java
│   │   │   │               │       └── service
│   │   │   │               │           ├── IDeptService.java
│   │   │   │               │           └── impl
│   │   │   │               │               └── DeptServiceImpl.java
│   │   │   │               ├── mybatisplus
│   │   │   │               │   └── generator
│   │   │   │               │       └── MysqlGenerator.java
│   │   │   │               └── Provider8003.java
│   │   │   └── resources
│   │   │       ├── application.yml
│   │   │       └── mapper
│   │   │           └── provider
│   │   │               └── DeptMapper.xml
│   │   └── test
│   │       └── java
└── pom.xml

测试服务提供者集群

1.启动三个eureka server 实例

2.启动三个服务提供者实例SpringCloud项目搭建实例-开源基础软件社区

3.分别访问 `

http://localhost:8001/provider/dept/list` ,`http://localhost:8002/provider/dept/list` ,`http://localhost:8003/provider/dept/list`SpringCloud项目搭建实例-开源基础软件社区

部门服务消费者模块

目录结构

deptmanagecloud
├── deptmanagecloud-consumer-9001
│   ├── pom.xml
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── com
│       │   │       └── omygod
│       │   │           └── springcloud
│       │   │               └── deptmanagecloud
│       │   │                   ├── AppConfig.java
│       │   │                   ├── Consumer9001.java
│       │   │                   └── controller
│       │   │                       └── DeptConsumerController.java
│       │   └── resources
│       │       └── application.yml
│       └── test
│           └── java
└── pom.xml

pom.xml

此时还未注册到 Eureka Server,所以不需要添加Eureka 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">
    <parent>
        <artifactId>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>deptmanagecloud-consumer-9001</artifactId>

    <dependencies>
        <!--引入自定义的jar-->
        <dependency>
            <groupId>com.omygod.springcloud</groupId>
            <artifactId>deptmanagecloud-api</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--引入Springboot启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--引入Springboot web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--spring-boot-maven-plugin插件作用,当运行“mvn package”进行打包时,会打包成一个可以直接运行的 JAR 文件,使用“Java -jar”命令就可以直接运行-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

server:
  port: 9001

启动类

package com.omygod.springcloud.deptmanagecloud;

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

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

新建AppConfig配置类

package com.omygod.springcloud.deptmanagecloud;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class AppConfig {

    /**
     * 注入http rest请求模板工具集,用来请求微服务提供者提供的服务
     *
     * @return
     */
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

新建消费者业务

package com.omygod.springcloud.deptmanagecloud.controller;

import com.omygod.springcloud.deptmanagecloud.provider.entity.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
public class DeptConsumerController {
    /**
     * 在未使用负载均衡配置前,需要指定请求的服务提供者地址
     */
    private static final String REST_URL_PREFIX = "http://localhost:8001";

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept getDept(@PathVariable(value = "id") Integer id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/provider/dept/get/" + id, Dept.class);
    }

    @RequestMapping("/consumer/dept/list")
    public List listDept() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/provider/dept/list", List.class);
    }

}

测试

访问 `

http://localhost:9001/consumer/dept/list` 如返回如下数据,则启动成功SpringCloud项目搭建实例-开源基础软件社区

服务消费者整合 Ribbon (客户端)负载均衡工具

此模块整合后,可通过服务名称访问服务提供者接口,不用再关心地址和端口号的问题,实现分布式从此开始。

  • 将服务消费者模块(deptmanagecloud-consumer-9001)复制一份,修改模块名称 deptmanagecloud-consumer-ribbon-9001
  • 修改主启动类名为 ConsumerRibbon9001
  • 在父工程的pom.xml添加模块deptmanagecloud-consumer-ribbon-9001
  • 在 deptmanagecloud-consumer-ribbon-9001模块进行修改,其它的地方暂不修改

修改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>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>deptmanagecloud-consumer-9001</artifactId>

    <dependencies>
        <!--引入自定义的jar-->
        <dependency>
            <groupId>com.omygod.springcloud</groupId>
            <artifactId>deptmanagecloud-api</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--引入Springboot启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--引入Springboot web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--使用Ribbon负载均衡组件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <!--引入Eureka 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--spring-boot-maven-plugin插件作用,当运行“mvn package”进行打包时,会打包成一个可以直接运行的 JAR 文件,使用“Java -jar”命令就可以直接运行-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

修改application.yml

server:
  port: 9001

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.hosts:7001/eureka/,http://eureka7002.hosts:7002/eureka/,http://eureka7003.hosts:7003/eureka/
    register-with-eureka: false

修改启动类

package com.omygod.springcloud.deptmanagecloud;

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

@SpringBootApplication
@EnableEurekaClient   // 添加eureka client 注解
public class ConsumerRibbon9001 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerRibbon9001.class, args);
    }
}

修改AppConfig配置类

package com.omygod.springcloud.deptmanagecloud;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class AppConfig {

    /**
     * 注入http rest请求模板工具集,用来请求微服务提供者提供的服务
     *
     * @return
     */
    @Bean
    @LoadBalanced  // 加上 @LoadBalanced 即可启用 ribbon 负载均衡
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

修改消费端的访问类(即controller下的类)

package com.omygod.springcloud.deptmanagecloud.controller;

import com.omygod.springcloud.deptmanagecloud.provider.entity.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
public class DeptConsumerController {
    /**
     * 在未使用负载均衡配置前,需要指定请求的服务提供者地址
     */
    //private static final String REST_URL_PREFIX = "http://localhost:8001";
    /**
     * 使用负载均衡后,此处需要替换成对应的服务名称,注意全要大写
     */
    private static final String REST_URL_PREFIX = "http://DEPTMANAGECLOUD-PROVIDER";

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept getDept(@PathVariable(value = "id") Integer id) {
        return restTemplate.getForObject(REST_URL_PREFIX + "/provider/dept/get/" + id, Dept.class);
    }

    @RequestMapping("/consumer/dept/list")
    public List listDept() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/provider/dept/list", List.class);
    }

}

测试

  • 启动三个eureka服务实例
  • 启动服务提供者实例
  • 启动服务消费者实例(deptmanagecloud-consumer-ribbon-9001)
  • 访问 http://localhost:9001/consumer/dept/list ,出现如下图所示,说明搭建成功

SpringCloud项目搭建实例-开源基础软件社区

测试集群环境负载均衡

测试前需要搭建服务提供者集群环境,具体查看搭建服务提供者集群章节。

启动三个eureka服务实例

启动三个服务提供者实例

启动服务消费者实例(deptmanagecloud-consumer-ribbon-9001)

连续访问http://localhost:9001/consumer/dept/list ,出现不同的数据表示成功

注:Ribbon 自定义负载均衡配置请参考官网

SpringCloud项目搭建实例-开源基础软件社区

整合 Feign 负载均衡

1.Feign组件具有Ribbon功能,使用Feign组件只需要添加一个注解和接口即可使用。

2.Feign= Ribbon + RestTemplate

复制模块

1.将服务消费者模块(`deptmanagecloud-consumer-9001`)复制一份,修改模块名称 `deptmanagecloud-consumer-feign-9001`

2.修改主启动类名为 `ConsumerFeign9001`

3.在父工程的pom.xml添加模块`deptmanagecloud-consumer-feign-9001`

4.在 `deptmanagecloud-consumer-feign-9001`模块进行修改,其它的地方暂不修改

pom.xml

1.修改通用API模块的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>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>deptmanagecloud-api</artifactId>

    <dependencies>
        <!--引入lombok插件,简化开发-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--mybatis-plus-annotation 注解包-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-annotation</artifactId>
        </dependency>

        <!--引入feign 负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

</project>

2. 修改 `deptmanagecloud-consumer-feign-9001` 模块的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>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>deptmanagecloud-consumer-feign-9001</artifactId>

    <dependencies>
        <!--引入自定义的jar-->
        <dependency>
            <groupId>com.omygod.springcloud</groupId>
            <artifactId>deptmanagecloud-api</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--引入Springboot启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--引入Springboot web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!--引入Eureka 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <!--spring-boot-maven-plugin插件作用,当运行“mvn package”进行打包时,会打包成一个可以直接运行的 JAR 文件,使用“Java -jar”命令就可以直接运行-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

server:
  port: 9001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.hosts:7001/eureka/,http://eureka7002.hosts:7002/eureka/,http://eureka7003.hosts:7003/eureka/
    register-with-eureka: false

修改启动类

package com.omygod.springcloud.deptmanagecloud;

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
@EnableFeignClients   //开启Feign负载均衡
@EnableEurekaClient
public class ConsumerFeign9001 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerFeign9001.class, args);
    }
}

新建一个Feign接口

接口存放位置最好与实体类在一起

package com.omygod.springcloud.deptmanagecloud.provider.service;

import com.omygod.springcloud.deptmanagecloud.provider.entity.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.List;

// 添加 Feign 注解,指定调用的服务
@FeignClient(value = "DEPTMANAGECLOUD-PROVIDER")
public interface DeptClientService {

    @GetMapping("/provider/dept/get/{id}")
    Dept getDept(@PathVariable(value = "id") Integer id);

    @GetMapping("/provider/dept/list")
    List<Dept> getDeptList();
}

修改controller

package com.omygod.springcloud.deptmanagecloud.controller;

import com.omygod.springcloud.deptmanagecloud.provider.entity.Dept;
import com.omygod.springcloud.deptmanagecloud.provider.service.DeptClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class DeptConsumerController {

    /**
     * 注入 Feign 接口
     */
    @Autowired
    DeptClientService deptClientService;

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept getDept(@PathVariable(value = "id") Integer id) {
        return deptClientService.getDept(id);
    }

    @RequestMapping("/consumer/dept/list")
    public List listDept() {
        return deptClientService.getDeptList();
    }
}

测试

同Ribbon负载均衡测试结果。

整合Hystrix容断器

复制一个服务提供者模块

修改启动类名,模块名称,父工程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">
    <parent>
        <artifactId>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>deptmanagecloud-provider-hystrix-8001</artifactId>

    <dependencies>
        <!--引入自定义的jar-->
        <dependency>
            <groupId>com.omygod.springcloud</groupId>
            <artifactId>deptmanagecloud-api</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!--根据业务,引入模块必要的jar-->

        <!--引入数据库连接相关jar包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>
        <!--引入 MyBatis-Plus 之后请不要再次引入 MyBatis 以及 MyBatis-Spring,以避免因版本差异导致的问题-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!--代码生成器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
        </dependency>
        <!--代码生成器模板-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.2</version>
        </dependency>

        <!--引入Springboot启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--引入Springboot web启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--引入Eureka 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!--引入Hystrix断路器-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        
    </dependencies>
    
    <build>
        <plugins>
            <!--spring-boot-maven-plugin插件作用,当运行“mvn package”进行打包时,会打包成一个可以直接运行的 JAR 文件,使用“Java -jar”命令就可以直接运行-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
</project>

application.yml

# 为区别未加hystrix的模块,修改实例名称
server:
  port: 8001

spring:
  application:
    name: deptmanagecloud-provider
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/deptmanage01
    username: root
    password: 12345678
    dbcp2:
      min-idle: 5
      initial-size: 5
      max-total: 5
      max-wait-millis: 200

eureka:
  instance:
    instance-id: deptmanagecloud-provider-hystrix-8001  # 实例名称
  client:  # 客户端注册进Eureka服务列表内
    service-url:
      defaultZone: http://eureka7001.hosts:7001/eureka/,http://eureka7002.hosts:7002/eureka/,http://eureka7003.hosts:7003/eureka/  # 如果是集群环境,Eureka的地址使用‘,’隔开

mybatis-plus:
  mapper-locations: classpath*:/mapper/provider/*.xml
  type-aliases-package: com.omygod.springcloud.entity
  type-aliases-super-type: java.lang.Object

修改启动类

package com.omygod.springcloud;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
// 启动Eureka客户端,注册服务
@EnableEurekaClient
// Mybatis plus 配置包扫描路径
@MapperScan("com.omygod.springcloud.deptmanagecloud.*.mapper")
// 开启断路器
@EnableCircuitBreaker
public class ProviderHystrix8001 {
    public static void main(String[] args) {
        SpringApplication.run(ProviderHystrix8001.class, args);
    }

    /**
     * 配置 mybatis plus 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}

修改客户端访问类

package com.omygod.springcloud.deptmanagecloud.provider.controller;


import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.omygod.springcloud.deptmanagecloud.provider.entity.Dept;
import com.omygod.springcloud.deptmanagecloud.provider.service.IDeptService;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author omygod
 * @since 2020-04-05
 */
@RestController
@RequestMapping("/provider/dept")
public class DeptController {

    @Autowired
    IDeptService deptService;

    @GetMapping("/get/{id}")
    // 当服务出现异常后调用指定的处理方法
    @HystrixCommand(fallbackMethod = "processHystrixGet")
    public Dept getDept(@PathVariable(value = "id") Integer id){
        Dept dept = deptService.getById(id);
        if(dept == null){
            // 模拟抛出异常的情况
            throw new RuntimeException("该ID: "+id+" 不存在");
        }
        return dept;
    }

    /**
     * 预期的处理异常返回数据
     * @return
     */
    public Dept processHystrixGet(@PathVariable(value = "id") Integer id){
        return new Dept().setDeptno(-1).setDeptname("该编号部门不存在").setDbsource("null");
    }


    @GetMapping("/list")
    public List<Dept> getDeptList(){
        return deptService.list();
    }

}

测试断路器

1.启动三个Eureka服务实例

2.启动加入Hystrix的服务提供者实例

3.启动服务消费者实例

4.获取不存在的部门SpringCloud项目搭建实例-开源基础软件社区

服务降级

1.服务降级是为了避免使用断路器这种方式而产生的方法膨胀

2.服务降级的实现只需要新增一个实现了 `FallbackFactory` 接口和相关注解即可

3.服务降级实现在客户端,与服务端没有关系

在 `通用API模块` 新增一个实现了 `FallbackFactory` 接口的实现类

package com.omygod.springcloud.deptmanagecloud.provider.service.impl;

import com.omygod.springcloud.deptmanagecloud.provider.entity.Dept;
import com.omygod.springcloud.deptmanagecloud.provider.service.DeptClientService;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

// 此注解不能少
@Component
public class DeptClientFallbackFactoryImpl implements FallbackFactory<DeptClientService> {
    /**
     * 当接口不能提供正常服务后,为了加快响应,将会调用此类下实现的对应的方法
     *
     * @param throwable
     * @return
     */
    @Override
    public DeptClientService create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public Dept getDept(Integer id) {
                return new Dept().setDeptno(-1).setDeptname("此服务提供者已停止服务").setDbsource("");
            }

            @Override
            public List<Dept> getDeptList() {
                // 返回空
                return null;
            }
        };
    }
}

在`@FeignClient `标注的地方加上 `fallbackFactory` 属性

package com.omygod.springcloud.deptmanagecloud.provider.service;

import com.omygod.springcloud.deptmanagecloud.provider.entity.Dept;
import com.omygod.springcloud.deptmanagecloud.provider.service.impl.DeptClientFallbackFactoryImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.List;

@FeignClient(value = "DEPTMANAGECLOUD-PROVIDER",fallbackFactory = DeptClientFallbackFactoryImpl.class)
public interface DeptClientService {

    @GetMapping("/provider/dept/get/{id}")
    Dept getDept(@PathVariable(value = "id") Integer id);

    @GetMapping("/provider/dept/list")
    List<Dept> getDeptList();
}

修改 `deptmanagecloud-consumer-feign-9001` 模块的 `application.yml`

server:
  port: 9001
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.hosts:7001/eureka/,http://eureka7002.hosts:7002/eureka/,http://eureka7003.hosts:7003/eureka/
    register-with-eureka: false

feign:
  hystrix:
    enabled: true # 开启服务降级

测试服务降级

1.启动三个Eureka服务实例

2.启动一个服务提供者( `

deptmanagecloud-provider-8001` )实例

3.启动 `

deptmanagecloud-consumer-feign-9001` 实例

4.查看Eureka状态SpringCloud项目搭建实例-开源基础软件社区

访问 `

http://localhost:9001/consumer/dept/get/2`SpringCloud项目搭建实例-开源基础软件社区

停掉 ``

deptmanagecloud-provider-8001`` 实例再次访问SpringCloud项目搭建实例-开源基础软件社区

整合Zuul网关

搭建Zuul网关工程

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>deptmanagecloud</artifactId>
        <groupId>com.omygod.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>deptmanagecloud-zuul-80</artifactId>

    <dependencies>
        <!--引入Springboot启动器-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!--引入Eureka 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!--引入Zuul-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!--spring-boot-maven-plugin插件作用,当运行“mvn package”进行打包时,会打包成一个可以直接运行的 JAR 文件,使用“Java -jar”命令就可以直接运行-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.yml

server:
  port: 8080
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.hosts:7001/eureka/,http://eureka7002.hosts:7002/eureka/,http://eureka7003.hosts:7003/eureka/
  instance:
    instance-id: gateway-80.com
    prefer-ip-address: true  # 显示IP
    
spring:
  application:
    name: deptmanagecloud-zuul-gateway

修改hosts文件

127.0.0.1   gateway-80.com

新建服务启动类

package com.omygod.springcloud.deptmanagecloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulGateway80 {
    public static void main(String[] args) {
        SpringApplication.run(ZuulGateway80.class, args);
    }
}

测试zuul网关

1.启动三个eureka服务实例

2.启动一个服务提供者

3.启动zuul网关实例

4.访问 `

http://gateway-80.com:8080/deptmanagecloud-provider/provider/dept/get/2` (由于本地的80端口被占用,改用8080端口)SpringCloud项目搭建实例-开源基础软件社区

配置路由规则,追加 application.yml 文件

zuul:
  routes:
    pr.serviceId: deptmanagecloud-provider
    pr.path: /pr/**   # 将 deptmanagecloud-provider 使用 pr 替代
  ignored-services: deptmanagecloud-provider  # # 当启用路由映射后,需要将真实的服务名隐藏,如需要忽略所有的微服务名称,改为 “*” 即可

SpringCloud项目搭建实例-开源基础软件社区

设置统一公共前缀:追加 application.yml 文件

zuul:
  routes:
    pr.serviceId: deptmanagecloud-provider
    pr.path: /pr/**
  ignored-services: deptmanagecloud-provider  # 当启用路由映射后,需要将真实的服务名隐藏,如需要忽略所有的微服务名称,改为 “*” 即可
  prefix: /lsd  # 添加统一前缀

SpringCloud项目搭建实例-开源基础软件社区

到此为止,关于使用SpringCloud搭建项目教程就结束了.

收藏
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐