# jee-fast
**Repository Path**: java-tools/jee-fast
## Basic Information
- **Project Name**: jee-fast
- **Description**: 基于SpringBoot、Vue.js、Element UI等主流前后端技术,采用前后端分离架构实现的后台权限管理系统
- **Primary Language**: Unknown
- **License**: AGPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 3
- **Created**: 2025-06-11
- **Last Updated**: 2025-06-11
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 后台权限管理系统jee-fast
jee-fast是基于SpringBoot、Vue.js、Element UI等主流前后端技术,采用前后端分离架构实现的后台权限管理系统,也是一款界面优雅、架构优良、代码简洁、功能完善的快速开发平台。
项目基于:书籍《Spring Boot + Spring Cloud + Vue + Element项目实战手把手教你开发权限管理系统》
# 1 功能介绍
* 系统登录:用户登录、token认证
* 系统管理:用户管理、机构管理、角色管理、菜单管理、字典管理、配置管理
* 日志管理:登录日志、操作日志
* 监控管理:在线用户、数据监控
* 开发文档
* 备份还原
* 主题切换
* 微服务:注册中心Consul,服务监控SpringBoot Admin,服务调用Ribbon、Fegin,服务熔断Hystrix、Turbine,服务网关SpringCloud Zuul,链路追踪Sleuth、ZipKin,配置中心Cloud Config、Bus
# 2 系统架构
## 2.1 前端架构

核心框架使用Vue.js,UI使用Element,前后端交互使用axios,模拟接口数据使用mock
## 2.2 后端架构

主题架构使用Spring Boot、Spring Security、Spring Cloud、Mybatis
注册中心为Consul
构建工具为Maven
数据库为MySQL
# 3 项目展示
1.登录界面

2.系统主页

3.用户管理

4.机构管理

5.角色管理

6.菜单管理

7.用户个人中心

# 4 前端项目介绍
## 4.1 技术选型
1. 前端框架:Vue 2.x
2. 页面组件:Element 2.x
3. 状态管理:Vuex 2.x
4. 后台交互 axios 0.18.x
5. 图标:Font Awesome 4.x
## 4.2 开发环境
1. [Visual Studio Code](https://code.visualstudio.com/)
提供浏览器下载太慢,可以将下载链接前面的`https://az764295.vo.msecnd.net/`换为`http://vscode.cdn.azure.cn/`。
2. [Node JS](http://nodejs.cn/download)
Node JS提供的NPM依赖管理和编译打包工具使用非常方便,要是用NPM就需要安装NodeJS。
* 安装打包工具webpack
`npm install webpack -g`
* 安装vue脚手架项目初始化工具vue-cli
`npm install vue-cli -g`
* 配置淘宝镜像
`npm install -g cnpm --registry=https://registry.npm.taobao.org`
安装成功后用cnpm代替npm命令即可。
* 安装node.js包管理器Yarn
`npm install yarn -g`
切换为淘宝镜像:
`yarn config set registry https://registry.npm.taobao.org`
NPM与Yarn命令关系:
| NPM | Yarn |
| ---- | ---- |
| npm install | yarn install |
| npm install --save [package] | yarn add [package] |
| npm install --save-dev [package] | yarn add [package] --dev |
| npm install --global [package] | yarn global add [package] |
| npm uninstall --save [package] | yarn remove [package] |
| npm uninstall --save-dev [package] | yarn remove [package] |
## 4.3 项目结构
```
jee-fast-ui
-- build:项目编译模块
-- config:项目配置模块
-- src:项目源码模块
-- assets: 静态资源,图标、字体、国际化信息
-- components: 组件库,封装常用组件
-- http:后台交互模块,统一后台接口请求API
-- i18n:国际化模块,使用Vue i18
-- mock:Mock模块,模拟接口调用并返回定制数据
-- permission:权限控制模块,处理权限认证逻辑
-- router:路由管理模块,负责页面路由配置
-- store:状态管理模块,提供组件之间状态共享
-- utils:工具模块,提供通用的工具方法
-- views:页面模块,各种页面视图组件
```
## 4.4 项目部署
1. 下载源码
2. 编译源码
在项目目录下打开cmd终端,执行`npm install`命令,下载依赖包。
3. 本地运行项目
执行`npm run dev`命令启动项目,启动后通过`http://localhost:8080`访问项目。
4. 服务器运行项目
执行`npm run build`命令,进行打包,打包后会生成dist目录。将dist目录直接放到web服务器(如Tomcat),启动服务器即可访问。
5. Mock开关
修改`src/mock/index.js`中的`openMock`变量开启或关闭Mock功能。开启Mock功能可以模拟大部分后台接口数据。
6. 修改配置
自定义端口修改`config/index.js`下的`port`属性。后台接口和备份服务器地址配置在`src/utils/global.js`。
# 5 后端项目介绍
## 5.1 开发环境
1. 运行环境:JDK1.8+
2. 开发工具:Eclipse
3. 数据库: MySQL
4. 构建工具:Maven
JDK、Ecplise、MySQL、Maven自行安装
5. 注册中心:consul
本系统采用Consul作为注册中心,Consul服务端需要独立安装,进入[官网](https://www.consul.io)下载后解压,进入Consul目录,cmd执行`consul agent -dev`启动服务。
-dev表示开发模式运行,-server表示服务模式运行。
启动成功后访问`http://localhost:8500`进入Consul服务管理界面。
6. 链路追踪:zipkin
Spring Cloud 2.0以后官方不支持自建Server了,改成提供编译好的jar包供用户使用。
(1)方法一:Java环境运行jar包
到[zipkin官网](https://zipkin.io/)下载jar包后执行
`java -jar zipkin-server-2.23.2-exec.jar --STORAGE_TYPE=elasticsearch --ES_HOSTS=127.0.0.1:9200`
使用elasticsearch存储方式,需要先安装并运行elasticsearch。
如果想简单通过内存方式启动:
`java -jar zipkin-server-2.23.2-exec.jar`。
(2)方法二:Docker部署
首先需要安装好Docker环境。
使用elasticsearch存储方式,先拉取ZipKin和Elasticsearch镜像
```
docker pull openzipkin/zipkin
docker pull docker.elastic.co/elasticsearch/elasticsearch:6.3.0
```
创建文件夹结构:
```
dockerfile
|- elasticsearch
| |- data
|- docker-compose.yml
```
创建模板文件docker-compose.yml,放在jee-fast-zipkin下:
```
version: '3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.11.1
container_name: elasticsearch
restart: always
networks:
- elk
ports:
- 9200:9200
volumes:
- ./elasticsearch/data:/usr/share/elasticsearch/data
environment:
- discovery.type=single-node
zipkin:
image: openzipkin/zipkin
container_name: zipkin
restart: always
networks:
- elk
ports:
- 9411:9411
environment:
- STORAGE_TYPE=elasticsearch
- ES_HOSTS=elasticsearch
networks:
elk:
```
进入dockerfile目录,启动服务:`docker-compose up -d`
如果想简单内存方式启动,只启动一个ZipKin容器即可:`docker run -d -p 9411:9411 openzipkin/zipkin`
通过`docker ps`目录查看进程。
访问`http://127.0.0.1:9411`查看zipkin界面。
7. 消息队列RabbitMQ
配置中心客户端需要使用到消息总线Spring Cloud Bus刷新配置,消息总线需要依赖RabbitMQ消息服务,所以如果需要配置中心服务,需先安装RabbitMQ。
安装RabbitMQ:
直接下载安装包安装或者使用docker安装:
```
# 拉取镜像
docker pull rabbitmq:management
# 查看镜像列表
docker images
# 创建容器
docker run -d --name rabbitmq -p 5671:5671 -p 5672:5672 -p 4369:4369
-p 25672:25672 -p 15671:15671 -p 15672:15672 rabbitmq:management
# 查看启动容器
docker ps
```
访问Web管理界面:`http://IP:15672`,系统默认账号:guest/guest
## 5.2 技术选型
1. 核心结技术:Spring Boot 2.x
2. 安全框架:Spring Security 5.x
3. 持久层框架:MyBatis 3.x
4. 数据库连接池:Druid 1.x
5. 日志管理:slf4j、log4j
6. 消息对列:RabbitMQ
7. 接口文档:Swagger 2.9.x
## 5.3 项目结构
```
jee-fast:聚合模块,一键执行打包所有模块
jee-fast-common:公共代码模块,主要放置一些工具类
jee-fast-core:核心业务代码模块,主要封装公共业务模块
jee-fast-admin:后台管理模块,包含用户、角色、菜单等
jee-fast-backup:系统数据备份模块
jee-fast-monitor:系统监控模块,监控应用
jee-fast-producer:服务提供者,测试模块1
jee-fast-producer2:服务提供者,测试模块2
jee-fast-consumer:服务消费者,测试模块
jee-fast-hystrix:熔断监控模块,实时监控Hystrix
jee-fast-zuul:服务网关模块,实现服务路由,外部调用微服务
```
## 5.4 项目部署
1. 下载源码
2. 编译源码
在fast-pom工程下执行`maven clean install`命令下载依赖。
3. 导入数据库
使用`doc/sql`下的数据库脚本jee-fast.sql,初始化数据库。同时修改fast-admin等工程下的application.yml文件中的数据源等配置信息。
4. 本地运行项目
项目具体启动方式如下:
* 基础服务
(1)注册中心Consul,基础服务
在consul安装目录下cmd执行`consul agent -dev`启动服务,启动成功后访问`http://localhost:8500`进入Consul服务管理界面。
(2)系统服务监控jee-fast-monitor,执行JeeFastMonitorApplication,启动监控服务。
启动成功后访问`http://localhost:8000`进入服务监控界面,wallboard页面显示当前监控的应用,单击应用进入应用监控详情页面,查看各种应用监控信息,比如应用环境、处理器消息、线程信息、类加载、堆栈使用和垃圾回收情况等。
Linux服务器
* 权限管理模块
(1)系统数据备份模块jee-fast-backup,执行JeeFastBackupApplication启动服务。
(2)管理后台模块jee-fast-admin,执行JeeFastAdminApplication启动服务。
* 其他微服务模块
执行JeeFast**Application启动服务,注意一些模块需要启动对应软件服务。
5. 服务器运行项目
执行`maven clean package`命令进行打包,将打包后的jar文件上传服务器,执行命令运行相应模块:
`nohup java -jar xxx.jar >run.log 2>&1 &`
## 5.5 使用微服务
### 5.5.1 注册中心
如果某个模块需要使用注册中心服务,进行如下配置:
(1)pom文件添加Consul注册中心依赖
```
org.springframework.cloud
spring-cloud-starter-consul-discovery
```
(2)修改配置文件,添加服务注册配置
```
spring:
cloud:
consul:
host: localhost
port: 8500
discovery:
serviceName: ${spring.application.name}
```
(3)修改启动类,添加@EnableDiscoveryClient,开启注册发现
启动注册中心服务和该模块,访问`http://localhost:8500`进入管理界面查看到该模块即为成功。
### 5.5.2 系统服务监控
如果某个模块需要使用监控服务,进行如下配置:
(1)pom文件添加客户端依赖
```
de.codecentric
spring-boot-admin-starter-client
2.2.3
```
(2)修改配置文件,添加服务监控配置
```
spring:
boot:
admin:
client:
url: "http://localhost:8000"
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
```
启动jee-fast-monitor服务和该模块,访问`http://localhost:8000`进入监控界面查看到该模块即为成功。
### 5.5.3 服务消费
服务提供者模块:jee-fast-producer*,执行JeeFastProducerApplication启动服务。
服务消费者模块:jee-fast-consumer,执行JeeFastConsumerApplication启动服务。
jee-fast-consumer服务消费者调用jee-fast-producer*服务提供者接口,提供了三种方式的示例:
(1)RestTemplate:RestTemplate:CallController.java
(2)RestTemplate + Ribbon注解:RibbonCallController.java
(3)Fegin声明式:FeginCallController.java
依次启动注册中心、服务提供者、服务消费者项目,访问jee-fast-consumer提供的示例接口,返回正确信息即为成功。
### 5.5.4 服务熔断
如果服务消费者需要使用服务熔断,进行如下配置:
因为Feign中已经依赖了Hystrix,所以不需要再依赖Hystrix了。
(1)修改配置文件,添加服务熔断配置
```
feign:
hystrix:
enabled: true
```
(2)创建失败回调处理类
创建回调类,实现需要熔断器的Service接口,实现对应的方法,返回调用失败后的信息(示例):
```
@Component
public class ProducerHystrixFallback implements ProducerService {
@RequestMapping("hello")
public String hello() {
// 返回调用失败后的信息
return "sorry, hello service call failed!";
}
}
```
Feign声明式服务接口的@FeignClient注解中添加fallback属性,绑定该失败回调处理类。
```
@FeignClient(name = "jee-fast-producer", fallback = ProducerHystrixFallback.class)
public interface ProducerService {
@RequestMapping("hello")
public String hello();
}
```
(3)Feign接口(示例)
```
@RestController
public class FeignCallController {
@Autowired
private ProducerService producerService;
@RequestMapping("feign/call")
public String call() {
return producerService.hello();
}
}
```
启动成功后,多次访问feign接口`http://localhost:8005/feign/call`返回正确结果,关闭调用的producer服务,再次访问,返回熔断回调信息,则说明熔断成功,重启producer服务,再次访问,服务可以访问,说明熔断器具有自我诊断功能。
如果需要使用熔断监控服务,请运行jee-fast-hystrix模块,执行JeeFastHystrixApplication启动服务。
启动成功后,访问`http://localhost:8501/hystrix`,在监控地址内输入`http://localhost:8005/hystrix.stream`,点击Monitor Stream开始监控,查看对应服务的熔断监控信息。输入`http://localhost:8501/turbine.stream`,可以查看Turibine聚合多个Hytrix消费者的熔断监控信息
### 5.5.5 服务网关
如果需要使用服务网关,请运行jee-fast-zuul模块,执行JeeFastZuulApplication启动服务。
访问示例接口:`http://localhost:8010/fegin/call`,返回正确结果,即说明Zuul成功转发请求并成功调用后端微服务。
### 5.5.6 链路追踪
如果需要使用链路追踪服务,必须安装ZipKin和Elasticsearch,并启动ZipKin服务。
如果某个模块需要使用链路追踪服务,进行如下配置:
(1)pom文件添加ZipKin依赖
```
org.springframework.cloud
spring-cloud-starter-zipkin
```
(2)修改配置文件,添加ZipKin配置
```
# 配置zipkin
spring:
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
# 样本采集量,默认为0.1
probability: 1
```
启动成功后,访问其接口会产生ZipKin数据,可以访问`http://localhost:9411`查看服务调用信息。
### 5.5.7 配置中心
如果需要配置中心服务,请运行jee-fast-config模块,执行JeeFastConfigApplication启动服务。
需要提前创建GIT配置仓库,放置配置文件。
启动成功后仓库中的配置文件会被转换成相应的Web接口,规则为:
* /{application}/{profile}[/{label}]
* [/{label}]/{application}-{profile}.yml
* [/{label}]/{application}-{profile}.properties
例如访问`http://localhost:8020/consumer/dev`返回dev配置文件的信息,访问`http://localhost:8020/consumer-dev.properties`返回配置文件的具体内容。
需要某个模块需要使用配置中心服务,进行如下配置:
(1)pom文件添加config依赖
```
org.springframework.cloud
spring-cloud-starter-config
```
(2)添加bootstrap.yml配置文件
添加config的配置,并把application.yml中的consul配置移到这里,因为在通过配置中心查找配置时需要通过注册中心的发现服务。
```
spring:
cloud:
# 配置consul注册中心
consul:
host: localhost
port: 8500
discovery:
serviceName: jee-fast-consumer
# 配置config配置中心
config:
discovery:
# 开启发现服务
enabled: true
# 配置中心服务名称
serviceId: jee-fast-config
# 对应{application}部分
name: consumer
# 对应{profile}部分
profile: dev
# git的分支,如果配置中心使用的是本地存储则该参数无用
label: master
```
config的配置先于application.yml,bootstrap.yml的加载也先于application.yml。
(3)添加SpringConfigController控制器
通过注解@Value("${hello}")声明hello属性从配置文件读取。
```
@RefreshScope
@RestController
public class SpringConfigController {
@Value("${hello}")
private String hello;
@RequestMapping("hello")
public String from() {
return this.hello;
}
}
```
启动注册中心、配置中心和该项目,访问`http://IP:PORT/hello`返回配置信息。
(4)使用Refresh机制
添加actuator依赖,spring-boot-starter包含actuator,所以不需要再添加actuator了。
在使用配置属性的类型中加上@RefreshScope注解。
开放健康检查接口:
```
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
```
配置文件发生变化后,post请求`http://IP:PORT/actuator/refresh`就会更新配置文件。
当客户端数量很多时刷新手动客户端很麻烦,此时可以使用Spring Cloud Bus。
(5)使用Spring Cloud Bus
需要安装并启动RabbitMQ。
添加消息总线相关依赖:
```
org.springframework.cloud
spring-cloud-starter-bus-amqp
```
修改配置bootstrap.yml,添加RabbitMQ相关配置:
```
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
```
* 解决客户端报错:No bean named 'configServerRetryInterceptor' available:
添加刷新拦截器配置:
```
public class RetryConfig {
@Bean
@ConditionalOnMissingBean(name = "configServerRetryInterceptor")
public RetryOperationsInterceptor configServerRetryInterceptor() {
return RetryInterceptorBuilder.stateless().backOffOptions(1000, 1.2, 5000).maxAttempts(10).build();
}
}
```
resources下新建/META-INF/spring.factories:
```
org.springframework.cloud.bootstrap.BootstrapConfiguration=com.ywy.consumer.config.RetryConfig
```
配置文件发生变化后,post请求`http://localhost:8020/actuator/bus-refresh`更新所有客户端的配置文件。
# 6 关键技术
## 6.1 Spring Boot
Spring Boot是由Pivotal团队提供,设计用来简化新Spring应用的初始搭建以及开发过程的开源框架。该框架遵循约定优于配置的规则,使用特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。
## 6.2 Spring Cloud
Spring Cloud是一个微服务框架,提供了一整套分布式系统解决方案。它为微服务架构开发中所涉及的服务治理、服务熔断、智能路由、链路追踪、消息总线、配置管理、集群状态等操作都提供了一种简单的开发方式。
Spring Cloud组件:
1. Netflix Eureka:基于REST服务的服务治理组件,包括服务注册中心、服务注册与服务发现机制的实现。
2. Netflix Hystrix:容错管理工具,实现断路器模式,通过控制服务的节点,从而对延迟和故障提供更强大的容错能力。
3. Netflix Ribbon:实现客户端负载均衡的服务调用组件。
4. Netflix Feign:基于Ribbon和Hystrix的声明式服务调用组件。
5. Netflix Zuul:微服务网关,提供动态路由,访问过滤等服务。
6. Spring Cloud Config:配置管理工具,支持使用Git存储配置内容,支持应用配置的外部化存储,支持客户端配置信息刷新、加解密配置内容等。
7. Spring Cloud Bus:事件、消息总线,用于在集群中传播状态变化,可与Spring Cloud Config联合实现热部署。
8. Spring Cloud Sleuth:日志收集工具包,封住了Dapper、ZipKin和HTrace操作。
9. Spring Cloud Consul:封装了Consul操作,Consul是一个服务发现与配置工具。
10. Spring Cloud Zookeeper:操作Zookeeper的工具包,用于使用zookeeper方式的服务注册和发现。
11. Spring Cloud Stream:数据流操作开发包,封装了与Redis、Rabbit、Kafka等发送接收消息的接口。
12. Spring Cloud Data Flow:大数据操作工具,通过命令行方式操作数据流。
13. Spring Cloud Security:安全工具包,为应用程序添加安全控制,主要指OAuth2。
## 6.3 Spring Security
Spring Security是一个强大且支持高度自定义的安全框架,可以为系统在登录认证和访问授权两大核心安全方面提供强有力的保障。
## 6.4 MyBatis
MyBatis是一款非常优秀的持久层框架,可以支持定制化SQL、存储过程以及高级映射等高级特性。MyBatis可以使用简单的XML或注解来配置和映射原生信息,将接口和Java的POJOs对象映射成数据库中的记录,使用MyBatis可以避免几乎所有的JDBC代码,无须手动设置参数和获取结果集。
## 6.5 Vue.js
Vue.js是一套构建用户界面的渐进式框架,Vue只关注视图层,采用自底而上增量开发的设计方式,Vue的目标是通过尽可能简单的API实现响应的数据绑定和组合的视图组件。
## 6.6 Element
Element是饿了么开源的一套前端UI框架,通过了较为丰富的组件,界面简洁优雅。Element分别提供了Vue.js、React和Angular的实现。
## 6.7 系统服务监控(Spring Boot Admin)
Spring Boot Admin是一个管理和监控Spring Boot应用程序的开源监控软件,针对spring-boot的actuator接口进行UI美化并封装,乐意在管理界面中浏览所有被监控spring-boot项目的基本信息,详细的Health信息、内存信息、JVM信息、垃圾回收信息、各种配置信息(如数据源、缓存列表和命中率)等,还可以直接修改logger的level,Spring Boot Admin提供的丰富详细的监控信息给Spring Boot应用的监控、维护和优化都带来了极大的便利。
## 6.8 注册中心(Consul)
Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其他分布式服务注册与发现的方案相比,Consul的方案更“一站式”,内置了服务注册与发现框架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案,不再需要依赖其他工具(比如ZooKeeper等),使用起来也比较简单。Consul使用Go语言编写,因此具有天然可移植性(支持Linux、Windows和Mac OS X);安装包仅包含一个可执行文件,方便部署,与Docker等轻量级容器可无缝配合。
## 6.9 服务消费(Ribbon、Feign)
在单体应用中,代码可以直接依赖,在代码中直接调用即可,但在微服务架构(分布式架构)中,服务都运行在各自的进程之中,甚至部署在不同的主机和不同的地区,就需要相关的远程调用技术了。
Spring Cloud体系里应用比较广泛的服务调用方式有两种:
(1)使用RestTemplate进行服务调用,可以通过Ribbon注解RestTemplate模板,使其拥有负载均衡的功能。
(2)使用Feign进行声明式服务调用,声明之后就行调用本地方法一样,Feign默认使用Ribbon实现负载均衡。
### 6.9.1 Ribbon
Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP的客户端的行为。为Ribbon配置服务提供者地址后,Ribbon就可基于某种负载均衡算法自动地帮助服务消费者去请求。Ribbion默认为我们提供了很短负载均衡算法,例如轮询、随机。我们也可以为Ribbon实现自定义的负载均衡算法。
Ribbon内置负载均衡策略:

### 6.9.2 Feign
Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端,使编写Web服务客户端变得更加简单。我们只需要通过创建接口并用注解来配置它即可完成对Web服务接口的绑定。它具备可插拔的注解支持,包括Feign注解、JAX-RS注解。它也支持可插拔的编码器和解码器。Spring Cloud Feign还扩展了对Spring MVC注解的支持,同时还整合了Ribbon来提供均衡负载的HTTP客户端实现。
## 6.10 服务熔断(Hystrix、Turbine)
### 6.10.1 雪崩效应
在微服务架构中,服务众多,通常会涉及多个服务层级的调用,一旦基础服务发生故障,很可能会导致级联故障,进而造成整个系统不可用,这种现象被称为服务雪崩效应。
服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用并将这种不可用逐渐放大的过程。
### 6.10.2 熔断器(CircuitBreaker)
熔断器如果电力过载保护器,它可以实现快速失败,如果它在一段时间内侦测到许多类似的错误,就回强迫其以后的调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。熔断器模式就像是那些容易导致错误操作的一种代理。这种代理能够记录最近调用发生错误的次数,然后决定使用允许操作继续,或者立即返回错误。熔断器是保护服务高可用的最后一道防线。
### 6.10.3 Hystrix特性
(1)断路器机制
当Hystrix Command请求后端服务失败数量超过一定比例,断路器会切换到开路状态(OPEN)。这时所有请求会直接失败而不会发送到后端服务。断路器保持在开路状态一段时间后,自动切换到半开路状态(HALF-OPEN)。这时会判断下一次请求的返回情况,如果请求成功,断路器切回闭路状态(CLOSE),否则重新切换到开路状态。一点后端服务不可用,断路器就回直接切断请求链,避免发送大量无效请求,从而影响系统吞吐量,并且断路器有自我检测并恢复的能力。
(2)fallback
fallback相当于降级操作。对于查询操作,我们可以实现一个fallback方法,当请求后端服务出现异常时,可以使用fallback方法返回的值。fallback方法的返回值一般是设置的默认值或者来自缓存。
(3)资源隔离
在Hystrix中主要通过线程池来实现资源隔离。在使用时根据调用的远程服务划分出多个线程池。这样做的优点是运行环境被隔离开了,就算调用服务的代码存在bug或者由于其他原因导致自己所在的线程池被耗尽,也不会对系统的其他服务造成影响,但代价就是维护多个线程池会对系统带来额外的性能开销。如果对性能有严格要求而且确信自己调用服务的客户端不会出现问题,就可以使用Hystrix的信号模式(Semaphores)来隔离资源。
### 6.10.4 Hystrix Dashboard
Hystrix Dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard我们可以直观地看到各Hystrix Command的请求响应时间、请求成功率等数据。
Hystrix Dashboard支持3种监控方式:
(1)单体Hystrix消费者:通过URL `http://hystrix-app:port/hystrix.stream`开启,实现对具体某个服务实例的监控。
(2)默认集群监控:通过URL `http://turbine-hostname:port/turbine.stream`开启,实现对默认集群的监控。
(3)自定义集群监控:通过URL `http://turbine-hostname:port/hostname.stream?cluster=[clusterName]`开启,实现对clusterName集群的监控。
监控界面参数说明:

## 6.10.5 Spring Cloud Turbine
汇总系统内多个服务的数据并显示到Hystrix Dashboard上。
## 6.11 服务网关(Zuul)
让客户端直接与各个微服务通信会有以下几个问题:
(1)客户端会多次请求不同的微服务,增加客户端的复杂性。
(2)存在跨域请求,在一定场景下处理会变得相对比较复杂。
(3)实现认证复杂,每个微服务都需要独立认证。
(4)难以重构,项目迭代可能导致微服务重新划分,如果客户端直接与微服务通信,那么重构将会很难实施。
(5)如果某些微服务使用了防火墙/浏览器不友好的协议,直接访问会有一定困难。
使用服务网关具有以下几个优点:
(1)易于监控。可在微服务网关收集监控数据并将其推送到外部系统进行分析。
(2)易于认证。可在服务网关上进行认证,然后转发请求到微服务,无须在每个微服务中进行认证。
(3)客户端只跟服务网关打交道,减少了客户端与各个微服务之间的交互次数。
(4)多渠道支持,可以根据不同客户端(Web端、移动端、桌面端等)提供不同的API服务网关。
### 6.11.1 Spring Cloud Zuul
服务网关是微服务架构中一个不可或缺的部分。在通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。
Spring CloudNetflix中的Zuul就担任了这样的角色,为微服务通过了前门保护的作用,同时将权限控制这些比较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。
在Spring Cloud体系中Spring Cloud Zuul封装了Zuul组件,作为一个API网关,负责提供负载均衡、反向代理和权限认证。
Zuul作为API网关服务,不同的客户端使用不同的负载将请求统一分发到后端的Zuul,再由Zuul转发到后端服务。为了保证Zuul的高可用,前端可以同时开启多个Zuul实例进行负载均衡。另外,Zuul的前端还可以使用Nginx或则F5再次进行负载均衡,从而保证Zuul的高可用性。
### 6.11.2 Zuul工作机制
(1)过滤器机制
Zuul的核心是一系列的filters,其作用类似Servlet框架的Filter,Zuul把客户端请求路由到业务处理逻辑过程中,这些filter在路由的特定时期参与了一些过滤处理,比如实现鉴权、流量转发、请求统计等功能。
Zuul运行机制:

(2)过滤器的生命周期
过滤器的生命周期分别为PRE、ROUTING、POST、ERROR。

Zuul中定义了四种标准过滤器类型,对应于请求的典型生命周期。基于这些过滤器可以实现各种丰富的功能。
* PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
* ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
* POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
* ERROR:在其他阶段发生错误时执行该过滤器。
Zuul默认实现的Filter:

除了默认的过滤器类型,Zuul允许我们创建自定义的过滤器类型。自定义过去器需要继承ZuulFilter,并实现ZuulFilter中的抽象方法。
(3)禁用指定的Filter
可以在application.yml中配置需要禁用filter,格式为zuul.[SimpleClassName].[filterType].disable=true。
### 6.11.3 默认路由规则
通过添加路由配置进行请求转发:
```
zuul:
# 接口前缀
# prefix: /v1
# 配置路由转发规则(示例)
routes:
ribbon:
path: /ribbon/**
serviceId: jee-fast-consumer
feign:
path: /feign/**
serviceId: jee-fast-consumer
```
如果后端微服务非常多,每一个都这样配置很麻烦,Spring Cloud Config已经帮我们做了默认配置。默认情况下,Zuul会代理所有注册到注册中心的微服务,并且Zuul的默认路由规则如下:`http://ZUUL_HOST:ZUUL_PORT/[微服务在注册中心的serviceId]/**`会被转发到serviceId对应得微服务。如果遵循默认路由规则,基本就没什么配置了。
### 6.11.4 路由熔断
Zuul作为Netflix组件,可以与Ribbon、Eureka和Hystrix等组件相结合,实现负载均衡、熔断器的功能。默认情况下Zuul和Ribbon相结合,实现了负载均衡。实现熔断器功能需要实现FallbackProvider接口。
实现该接口有两个方法:
(1)getRoute(),用于指定熔断器功能应用于哪些路由的服务,如果需要所有的路由都加熔断功能,则返回"*";
(2)fallbackResponse(),为进入熔断器功能时执行的逻辑。
## 6.12 链路追踪(Sleuth、Zipkin)
在微服务架构中,随着业务发展,系统拆分导致系统调用链路愈发复杂,一个看似简单的前端请求可能最终需要调用很多次后端服务才能完成,那么当整个请求出现问题时,我们很难得知到底是哪个服务出了问题导致的,这是就需要解决一个问题,即如何快速定位服务故障点,分布式系统调用链路追踪技术就此诞生了。
### 6.12.1 ZipKin
ZipKin是一个由Twitter公司提供并开源的分布式的跟踪系统,它可以帮助收集服务的时间数据,以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。
每个服务向ZipKin报告定时数据,ZipKin会根据调用关系通过ZipKin UI生成依赖关系图,展示多少跟踪请求经过了哪些服务,该系统让开发者可通过一个Web前端轻松地收集和分析数据,例如用户每次请求服务的处理时间等,可非常方便地监测系统中存在的瓶颈。
ZinKin提供了可插拔数据存储方式:In-Memory、MySQL、Cassandra以及Elasticsearch。我们可以根据需求选择不同的存储方式,生成环境一般都需要持久化。
### 6.12.2 Spring Cloud Sleuth
一般而言,一个分布式服务追踪系统,主要由3部分组成:数据收集、数据存储和数据展示。
Spring Cloud Sleuth为服务之间的调用提供链路追踪,提供Sleuth可以很清楚地了解到一个服务请求经过了哪些服务,每个服务处理花费了多长时间,从而让我们可以很方便地理清各微服务间的调用关系。此外,Sleuth还可以帮助我们:
(1)耗时分析:通过Sleuth可以很方便地了解到每个采样请求的耗时,从而分析出哪些服务调用比较耗时。
(2)可视化错误:对于程序未捕捉的异常,可以通过集成ZipKin服务在界面上看到。
(3)链路优化:对于调用比较频繁的服务,可以针对这些服务实施一些优化措施。
Spring Cloud Sleuth可以结合ZipKin,将信息发送给ZipKin,利用ZipKin的存储来存储信息,利用ZipKin UI来展示数据。
## 6.13 配置中心(Spring Config)
在分布式系统中,每个项目都有各种配置文件,且随着服务的增加而不断增多。某一个基础服务信息变更都会导致一系列服务的更新和重启,运维麻烦,极易出错。配置中心便由此应运而生。
目前市面上的配置中心很多,如Spring Cloud Config、Apache Commons Configuration、淘宝的diamond、百度的disconf、360的QConf等。
### 6.13.1 Spring Cloud Config
Spring Cloud Config是一套为分布式系统中的基础设施和微服务应用提供集中化配置的管理方案,分为服务端与客户端两个部分。服务端也称为分布式配置中心,是一个独立的微服务应用,用来连接配置仓库并为客户端提供获取配置信息。客户端是微服务架构中的各个微服务应用或基础设施,它们通过指定的配置中心来管理服务相关的配置内容,并在启动时从配置中心获取和加载配置信息。
Spring Cloud Config对服务端和客户端中的环境变量和属性配置实现了抽象映射,所以除了适用于Spring应用,也可以在任何其他语言中使用。Spring Cloud Config实现的配置中心默认采用Git来存储配置信息,所以使用Spring Cloud Config构建的配置服务器天然就支持对微服务应用配置信息的版本管理,并且可以通过Git客户端工具非常方便地管理和访问配置内容。当然它也提供了对其他存储方式的支持,如SVN仓库、本地化文件系统等。
### 6.13.2 Refresh机制
Spring Boot项目只有在启动时加载配置文件信息,Git仓库配置修改后,虽然配置中心服务器能够读取最新的提交信息,但配置中心客户端确不会重新读取,以至于不能基石地读取更新后的配置信息。
Refresh机制是Spring Cloud Config提供的一种刷新机制,它允许客户端提供POST方法触发各自的/refresh,主要依赖spring-boot-starter-actuator包就拥有了/refresh的功能。
### 6.13.3 Spring Cloud Bus
Spring Cloud Bus被大家称为消息总线,通过轻量级的消息代理来连接各个分布的节点,可以利用消息对列的广播机制在分布式系统中进行消息传播。通过消息总线可以实现很多业务功能,其中对于配置中心客户端刷新就是一个非常典型的使用场景。
消息总线的作用流程:

Spring Cloud Bus进行配置更新的步骤如下:
1. 提交代码触发post请求给/actuator/bus-refresh。
2. Server端接收到请求并发给Spring Cloud Bus。
3. Spring Cloud Bus接到消息并通知给其他客户端。
4. 其他客户端接收到通知,请求Server端获取最新配置。
5. 全部客户端均获取到最新的配置。
# 7 数据库设计
## 7.1 数据库设计原则
1. 表的主键采用长整型的“编号”字段
2. 所有表共有字段:编号、创建人、创建时间、更新人、更新时间
3. 表间关系采用各表编号进行关联查询,不定义数据库外键
## 7.2 数据库表结构
(1)用户表(sys_user)
用户表包含用户信息,主要有编号、用户名、昵称、密码、邮箱、手机号等字段,通过dept_id与机构表关联,表明所属机构。
(2)角色表(sys_role)
角色表代表用户角色,用户拥有角色,角色拥有菜单,菜单拥有权限标识。所以不同的角色拥有不同的权限,角色表主要有编号、角色名、备注等字段。
(3)机构表(sys_dept)
机构代表一种组织机构,可以有子机构,用户归属于机构。机构表主要有编号、机构名称、上级机构等字段。
(4)菜单表(sys_menu)
菜单分为目录、菜单和操作按钮三种类型,可以进行权限控制,菜单表主要有编号、菜单名称、父菜单、菜单类型、菜单图标、菜单URL、菜单权限等字段
(5)用户角色表(sys_user_role)
用户角色表是用户和角色的中间表,通过用户id和角色id分别和用户表和角色表关联。
(6)角色菜单表(sys_role_menu)
角色菜单表是角色和菜单的中间表,通过角色id和菜单id分别和角色表和菜单表关联。
(7)角色机构表(sys_role_dept)
角色机构表是角色和机构的中间表,通过角色id和机构id分别和角色表和机构表关联。
(8)字典表(sys_dict)
字典表主要存储系统采用的枚举类型数据,主要包含编号、标签、数据值、类型等字段。
(9)配置表(sys_config)
配置表主要存储系统配置信息,主要包含编号、标签、数据值、类型等字段。
(10)操作日志表(sys_log)
操作日志表主要记录系统用户的日常操作信息,主要包含编号、用户名、用户操作、请求方法、请求参数、执行时长、IP地址等字段。
(11)登录日志表(sys_login_log)
登录日志表主要记录用户登录和退出状态,主要包含编号、用户名、登录状态、IP地址等字段,可以根据status状态统计在线用户信息。
# 8 跨域解决方案
## 8.1 什么是跨域
同源策略:为了保障浏览器的安全,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。同源策略是浏览器安全的基石。
如果一个请求地址里协议、域名和端口号都相同就属于同源。
依据浏览器的同源策略,非同源脚本不可操作其他源下的对象,如果想要操作就需要跨域。
在同源策略下,非同源的网站之间不能发送Ajax请求,如果需要,可通过降域或其他技术实现。
## 8.2 CORS技术
为了解决浏览器跨域问题,W3C提出了跨域资源共享方案,即CORS(Cross-Origin Resource Sharing)。
CORS可以在不破坏既有规则的情况下,通过后端服务器实现CORS接口,从而实现跨域通信。CORS将请求分为简单请求和非简单请求,分别对跨域通信提供了支持。
### 8.2.1 简单请求
简单请求:
(1)请求方式只能是:HEAD、GET、POST
(2)请求头信息只能包含以下字段:
* Accept
* Accept-Language
* Content-Language
* Content-Type(仅限于application/x-www-form-urkencoded、multipart/form-data、text/plain类型)
对于简单请求,CORS的策略是请求时在请求头中增加一个Origin字段,服务器收到请求后,根据该字段判断是否允许该请求访问。
如果允许,就在HTTP头信息中添加以下字段,并返回正确结果:
* Access-Control-Allow-Origin:指定允许请求的域
* Access-Control-Allow-Credentials:可选,是否允许后续请求携带验证信息(cookies)
* Access-Control-Expose-Headers:可选,允许客户端拿到的字段。无论是否设置,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma都可以拿到。
### 8.2.2 非简单请求
对于非简单请求的跨域请求,浏览器会在真实请求发出前增加一次OPTION请求,称为预检请求(preflight request)。预检请求会将真实请求的信息添加到HTTP头信息字段中,询问服务器是否允许这样的操作。
与简单请求相比,除了Origin,还多了:
* Access-Control-Request-Method:请求使用的HTTP方法
* Access-Control-Request-Headers:请求中包含的自定义头字段
服务器收到请求时,需要对Origin、Access-Control-Request-Method、Access-Control-Request-Headers分别进行验证,验证通过后,会在返回HTTP头信息中添加:
* Access-Control-Allow-Origin:指定允许请求的域
* Access-Control-Allow-Methods:服务器允许的所有请求方法
* Access-Control-Allow-Headers:服务器允许的所有请求头字段
* Access-Control-Allow-Credentials:是否允许后续请求携带验证信息(cookies)
* Access-Control-Max-Age:预检请求的有效期,单位为秒。有效期内不会重复发送预检请求。
当预检请求通过后,浏览器才会发送真实请求到服务器,这样就实现了跨域资源的请求访问。
## 8.3 CORS实现
```
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 允许跨域访问的路径
.allowedOrigins("*") // 允许跨域访问的源
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许跨域访问的请求方法
.allowedHeaders("*") // 允许的请求头字段
.allowCredentials(true) // 允许后续请求携带验证信息(cookie)
.maxAge(16800); // 预检请求有效期
}
}
```