SpringCloud项目搭建实例
作者 | 星空XXL
来源 | 今日头条
SpringCloud介绍
SpringCloud是基于SpringBoot提供的一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件。
项目说明
以搭建一个部门管理系统为例,记录使用SpringCloud搭建项目的过程,使用的组件包括 Eureka、Ribbon、Fegin、Hystrix、Zuul等。
组件介绍(纯手工制作^-^)
Eureka 服务注册与发现
Ribbon和Feign负载均衡
Hystrix服务熔断
- 服务熔断
某个服务故障或者异常,类似现实世界中的“保险丝”,当某个异常条件被触发,直接熔断整个服务,而不是一直等到此服务超时。
- 服务降级
就是当某个服务熔断后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值,这样做,虽然服务水平下降了,但好歹可用,比直接挂掉要强。
Zuul网关
搭建父工程
目录结构
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.如出现如下页面,则启动成功
搭建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 ,出现如上图所示页面,则集群搭建成功
此时的父工程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.启动三个服务提供者实例
3.分别访问 `
http://localhost:8001/provider/dept/list` ,`http://localhost:8002/provider/dept/list` ,`http://localhost:8003/provider/dept/list`
部门服务消费者模块
目录结构
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` 如返回如下数据,则启动成功
服务消费者整合 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 ,出现如下图所示,说明搭建成功
测试集群环境负载均衡
测试前需要搭建服务提供者集群环境,具体查看搭建服务提供者集群章节。
启动三个eureka服务实例
启动三个服务提供者实例
启动服务消费者实例(deptmanagecloud-consumer-ribbon-9001)
连续访问http://localhost:9001/consumer/dept/list ,出现不同的数据表示成功
注:Ribbon 自定义负载均衡配置请参考官网
整合 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.获取不存在的部门
服务降级
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状态
访问 `
http://localhost:9001/consumer/dept/get/2`
停掉 ``
deptmanagecloud-provider-8001`` 实例再次访问
整合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端口)
配置路由规则,追加 application.yml 文件
zuul:
routes:
pr.serviceId: deptmanagecloud-provider
pr.path: /pr/** # 将 deptmanagecloud-provider 使用 pr 替代
ignored-services: deptmanagecloud-provider # # 当启用路由映射后,需要将真实的服务名隐藏,如需要忽略所有的微服务名称,改为 “*” 即可
设置统一公共前缀:追加 application.yml 文件
zuul:
routes:
pr.serviceId: deptmanagecloud-provider
pr.path: /pr/**
ignored-services: deptmanagecloud-provider # 当启用路由映射后,需要将真实的服务名隐藏,如需要忽略所有的微服务名称,改为 “*” 即可
prefix: /lsd # 添加统一前缀
到此为止,关于使用SpringCloud搭建项目教程就结束了.