Răsfoiți Sursa

:tada: BladeX通用业务工程已安排上

smallchill 7 ani în urmă
părinte
comite
24f7e2a66f
53 a modificat fișierele cu 2868 adăugiri și 2 ștergeri
  1. 21 0
      .editorconfig
  2. 27 0
      .gitignore
  3. 33 0
      LICENSE
  4. 129 2
      README.md
  5. 52 0
      blade-common/pom.xml
  6. 28 0
      blade-common/src/main/java/org/springblade/common/cache/CacheNames.java
  7. 32 0
      blade-common/src/main/java/org/springblade/common/config/BladeCommonConfiguration.java
  8. 118 0
      blade-common/src/main/java/org/springblade/common/constant/CommonConstant.java
  9. 42 0
      blade-common/src/main/java/org/springblade/common/launch/LauncherServiceImpl.java
  10. 26 0
      blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java
  11. 8 0
      blade-common/src/main/resources/banner.txt
  12. 15 0
      blade-gateway/Dockerfile
  13. 154 0
      blade-gateway/pom.xml
  14. 39 0
      blade-gateway/src/main/java/org/springblade/gateway/GateWayApplication.java
  15. 86 0
      blade-gateway/src/main/java/org/springblade/gateway/config/ErrorHandlerConfiguration.java
  16. 115 0
      blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java
  17. 58 0
      blade-gateway/src/main/java/org/springblade/gateway/controller/DiscoveryClientController.java
  18. 63 0
      blade-gateway/src/main/java/org/springblade/gateway/filter/RequestGlobalFilter.java
  19. 116 0
      blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java
  20. 44 0
      blade-gateway/src/main/java/org/springblade/gateway/handler/HystrixFallbackHandler.java
  21. 55 0
      blade-gateway/src/main/java/org/springblade/gateway/handler/SwaggerResourceHandler.java
  22. 60 0
      blade-gateway/src/main/java/org/springblade/gateway/handler/SwaggerSecurityHandler.java
  23. 60 0
      blade-gateway/src/main/java/org/springblade/gateway/handler/SwaggerUiHandler.java
  24. 78 0
      blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java
  25. 25 0
      blade-gateway/src/main/resources/bootstrap.yml
  26. 17 0
      blade-service-api/blade-demo-api/pom.xml
  27. 64 0
      blade-service-api/blade-demo-api/src/main/java/org/springblade/demo/entity/Notice.java
  28. 50 0
      blade-service-api/blade-demo-api/src/main/java/org/springblade/demo/feign/INoticeClient.java
  29. 20 0
      blade-service-api/blade-demo-api/src/main/java/org/springblade/demo/vo/NoticeVO.java
  30. 82 0
      blade-service-api/pom.xml
  31. 15 0
      blade-service/blade-demo/Dockerfile
  32. 61 0
      blade-service/blade-demo/pom.xml
  33. 38 0
      blade-service/blade-demo/src/main/java/org/springblade/demo/DemoApplication.java
  34. 109 0
      blade-service/blade-demo/src/main/java/org/springblade/demo/controller/NoticeController.java
  35. 47 0
      blade-service/blade-demo/src/main/java/org/springblade/demo/feign/NoticeClient.java
  36. 47 0
      blade-service/blade-demo/src/main/java/org/springblade/demo/mapper/NoticeMapper.java
  37. 39 0
      blade-service/blade-demo/src/main/java/org/springblade/demo/mapper/NoticeMapper.xml
  38. 38 0
      blade-service/blade-demo/src/main/java/org/springblade/demo/service/INoticeService.java
  39. 39 0
      blade-service/blade-demo/src/main/java/org/springblade/demo/service/impl/NoticeServiceImpl.java
  40. 10 0
      blade-service/blade-demo/src/main/resources/application-dev.yml
  41. 10 0
      blade-service/blade-demo/src/main/resources/application-prod.yml
  42. 10 0
      blade-service/blade-demo/src/main/resources/application-test.yml
  43. 61 0
      blade-service/pom.xml
  44. 160 0
      pom.xml
  45. 2 0
      script/docker/.env
  46. 96 0
      script/docker/deploy.sh
  47. 139 0
      script/docker/docker-compose.yml
  48. 19 0
      script/docker/nacos/init.d/custom.properties
  49. 67 0
      script/docker/nginx/api/nginx.conf
  50. 10 0
      script/docker/nginx/web/html/index.html
  51. 60 0
      script/docker/nginx/web/nginx.conf
  52. 1 0
      script/service.cmd
  53. 73 0
      script/service.sh

+ 21 - 0
.editorconfig

@@ -0,0 +1,21 @@
+# http://editorconfig.org
+root = true
+
+# 空格替代Tab缩进在各种编辑工具下效果一致
+[*]
+indent_style = space
+indent_size = 4
+charset = utf-8
+end_of_line = lf
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.java]
+indent_style = tab
+
+[*.{json,yml}]
+indent_size = 2
+
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false

+ 27 - 0
.gitignore

@@ -0,0 +1,27 @@
+# maven #
+target
+
+logs
+
+# windows #
+Thumbs.db
+
+# Mac #
+.DS_Store
+
+# eclipse #
+.settings
+.project
+.classpath
+.log
+*.class
+
+# idea #
+.idea
+*.iml
+
+# Package Files #
+*.jar
+*.war
+*.ear
+/target

+ 33 - 0
LICENSE

@@ -0,0 +1,33 @@
+BladeX商业授权许可协议
+
+一、 知识产权:
+BladeX系列产品知识产权归BladeX团队独立所有
+
+二、 许可:
+1. 在您完全接受并遵守本协议的基础上,本协议授予您使用BladeX的某些权利和非独占性许可。
+2. 本协议中,将本产品使用用途分为“专业版用途”和“企业版用途”。
+3. “专业版用途”定义:指个人在非团体机构中使用本产品并用于商业目的。
+4. “企业版用途”定义:指团体机构(例如公司企业、政府、学校、军队、医院、社会团体等各类组织)出于任何目的使用本产品(任何目的包括商业目的或非盈利目的)。
+
+三、 约束和限制:
+1. 本产品只能由您为本协议许可的目的而使用,您不得透露给任何第三方;
+2. 从本产品取得的任何信息、软件、产品或服务,您不得对其进行修改、改编或基于以上内容创建同种类别的衍生产品并售卖。
+3. 您不得对本产品以及与之关联的商业授权进行发布、出租、销售、分销、抵押、转让、许可或发放子许可证。
+4. 本产品商业授权版可能包含一些独立功能或特性,这些功能只有在您购买商业授权后才可以使用。在未取得商业授权的情况下,您不得使用、尝试使用或复制这些授权版独立功能。
+5. 若您的客户要求以源码方式交付软件,需缴纳企业版授权费用,否则本产品部分不得提供源码。
+
+四、 不得用于非法或禁止的用途:
+您在使用本产品或服务时,不得将本产品产品或服务用于任何非法用途或本协议条款、条件和声明禁止的用途。
+
+五、 免责说明:
+1. 本产品按“现状”授予许可,您须自行承担使用本产品的风险。BladeX团队不对此提供任何明示、暗示或任何其它形式的担保和表示。在任何情况下,对于因使用或无法使用本软件而导致的任何损失(包括但不仅限于商业利润损失、业务中断或业务信息丢失),BladeX团队无需向您或任何第三方负责,即使BladeX团队已被告知可能会造成此类损失。在任何情况下, BladeX团队均不就任何直接的、间接的、附带的、后果性的、特别的、惩戒性的和处罚性的损害赔偿承担任何责任,无论该主张是基于保证、合同、侵权(包括疏忽)或是基于其他原因作出。
+2. 本产品可能内置有第三方服务,您应自行评估使用这些第三方服务的风险,由使用此类第三方服务而产生的纠纷,全部责任由您自行承担。
+3. BladeX团队不对使用本产品构建的网站中任何信息内容以及导致的任何版权纠纷、法律争议和后果承担任何责任,全部责任由您自行承担。
+4. BladeX团队可能会经常提供产品更新或升级,但BladeX团队没有为根据本协议许可的产品提供维护或更新的责任。
+
+六、 权利和所有权的保留:
+BladeX团队保留所有未在本协议中明确授予您的所有权利。BladeX团队保留随时更新本协议的权利,并只需公示于对应产品项目的LICENSE文件,无需征得您的事先同意且无需另行通知,更新后的内容应于公示即时生效。您可以随时访问产品地址并查阅最新版许可条款,在更新生效后您继续使用本产品则被视作您已接受了新的条款。
+
+七、 协议终止
+1. 您一旦开始复制、下载、安装或者使用本产品,即被视为完全理解并接受本协议的各项条款,在享有上述条款授予的许可权力同时,也受到相关的约束和限制,本协议许可范围以外的行为,将直接违反本协议并构成侵权。
+2. 一旦您违反本协议的条款,BladeX团队随时可能终止本协议、收回许可和授权,并要求您承担相应法律和经济责任。

+ 129 - 2
README.md

@@ -1,3 +1,130 @@
-# BladeX-Biz
+## BladeX是什么
+* BladeX 是一个基于 Spring Boot 2 & Spring Cloud Greenwich & Mybatis 等核心技术,用于快速构建中大型系统的基础框架
+* 已稳定生产近一年,经历了从Camden->Greenwich的技术架构,也经历了从FatJar->Docker->K8S+Jenkins的部署架构
+* 采用前后端分离的模式,前端开发两个框架:Sword(基于React、Ant Design)、Saber(基于Vue、ElementUI)
+* 后端采用SpringCloud系列,对其基础组件做了高度的封装,单独出一个后端核心框架:BladeX-Tool
+* BladeX-Tool已推送至Maven私有库,直接引入减少工程的模块与依赖,可更注重于业务开发
+* 集成Sentinel从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性
+* 注册中心、配置中心选型Nacos,为工程瘦身的同时加强各模块之间的联动
+* 使用Traefik进行反向代理,监听后台变化自动化应用新的配置文件
+* 集成Oauth2协议,完美支持了多终端的接入与认证授权
+* 集成工作流Flowable,复杂流程需求不再难办
+* 创建多租户模式,发布简单,数据隔离轻松
+* 项目分包明确,规范微服务的开发模式
 
-BladeX 业务工程专用模块
+## 商业授权
+* 您一旦开始复制、下载、安装或者使用本产品,即被视为完全理解并接受本协议的各项条款
+* 更多详情请看:[BladeX商业授权许可协议](https://gitee.ltd/blade/BladeX/src/master/LICENSE)
+
+## 官网
+* 官网地址:[https://bladex.vip](https://bladex.vip)
+
+## 在线演示
+* Sword演示地址:[https://sword.bladex.vip](https://sword.bladex.vip)
+* Saber演示地址:[https://saber.avue.top](https://saber.avue.top)
+
+## 后端项目地址
+* [BladeX](https://gitee.ltd/blade/BladeX)
+
+## 单工程SpringBoot版
+* [BladeX-Boot](https://gitee.ltd/blade/BladeX-Boot)
+
+## 前端项目地址
+* [Sword--基于React](https://gitee.ltd/blade/Sword)
+* [Saber--基于Vue](https://gitee.ltd/blade/Saber)
+
+## 会员计划及交流群
+* [会员计划及交流群](https://gitee.com/smallc/SpringBlade/wikis/SpringBlade会员计划)
+
+## 技术文档
+* [Blade开发手册](https://www.kancloud.cn/smallchill/blade)
+
+## 工程结构
+``` 
+BladeX
+├── blade-auth -- 授权服务提供
+├── blade-common -- 常用工具封装包
+├── blade-gateway -- Spring Cloud 网关
+├── blade-ops -- 运维中心
+├    ├── blade-admin -- spring-cloud后台管理
+├    ├── blade-develop -- 代码生成
+├── blade-service -- 业务模块
+├    ├── blade-desk -- 工作台模块 
+├    ├── blade-log -- 日志模块 
+├    ├── blade-system -- 系统模块 
+├    └── blade-user -- 用户模块 
+├── blade-service-api -- 业务模块api封装
+├    ├── blade-desk-api -- 工作台api 
+├    ├── blade-dict-api -- 字典api 
+├    ├── blade-system-api -- 系统api 
+└──  └── blade-user-api -- 用户api 
+```
+
+# 界面
+## 监控界面一览
+<table>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-k8s1.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-k8s2.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-grafana.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-harbor.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-traefik.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-traefik-health.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-nacos.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-sentinel.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-admin1.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-admin2.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-swagger1.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/springblade-swagger2.png"/></td>
+    </tr>
+</table>
+
+## Sword界面一览
+<table>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-main.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-menu.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-menu-edit.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-menu-icon.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-role.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-user.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-dict.png "/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-log.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-locale-cn.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/sword-locale-us.png"/></td>
+    </tr>
+</table>
+
+## Saber界面一览
+<table>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/saber-user.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/saber-role.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/saber-dict.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/saber-dict-select.png"/></td>
+    </tr>
+    <tr>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/saber-log.png"/></td>
+        <td><img src="https://gitee.com/smallc/SpringBlade/raw/master/pic/saber-code.png"/></td>
+    </tr>
+</table>

+ 52 - 0
blade-common/pom.xml

@@ -0,0 +1,52 @@
+<?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>BladeX-Biz</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.0.0.RC9</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-common</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-launch</artifactId>
+            <version>${bladex.tool.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-auto</artifactId>
+            <version>${bladex.tool.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                    <finalName>${project.name}</finalName>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>${docker.plugin.version}</version>
+                <configuration>
+                    <skipDockerBuild>true</skipDockerBuild>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 28 - 0
blade-common/src/main/java/org/springblade/common/cache/CacheNames.java

@@ -0,0 +1,28 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.common.cache;
+
+/**
+ * 缓存名
+ *
+ * @author Chill
+ */
+public interface CacheNames {
+
+	String NOTICE_ONE = "blade:notice:one";
+
+}

+ 32 - 0
blade-common/src/main/java/org/springblade/common/config/BladeCommonConfiguration.java

@@ -0,0 +1,32 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.common.config;
+
+
+import lombok.AllArgsConstructor;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 公共封装包配置类
+ *
+ * @author Chill
+ */
+@Configuration
+@AllArgsConstructor
+public class BladeCommonConfiguration {
+
+}

+ 118 - 0
blade-common/src/main/java/org/springblade/common/constant/CommonConstant.java

@@ -0,0 +1,118 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.common.constant;
+
+import org.springblade.core.launch.constant.AppConstant;
+
+/**
+ * 通用常量
+ *
+ * @author Chill
+ */
+public interface CommonConstant {
+
+	/**
+	 * nacos dev 地址
+	 */
+	String NACOS_DEV_ADDR = "127.0.0.1:8848";
+
+	/**
+	 * nacos prod 地址
+	 */
+	String NACOS_PROD_ADDR = "172.30.0.48:8848";
+
+	/**
+	 * nacos test 地址
+	 */
+	String NACOS_TEST_ADDR = "172.30.0.48:8848";
+
+	/**
+	 * sentinel dev 地址
+	 */
+	String SENTINEL_DEV_ADDR = "127.0.0.1:8858";
+
+	/**
+	 * sentinel prod 地址
+	 */
+	String SENTINEL_PROD_ADDR = "172.30.0.58:8858";
+
+	/**
+	 * sentinel test 地址
+	 */
+	String SENTINEL_TEST_ADDR = "172.30.0.58:8858";
+
+	/**
+	 * sword 系统名
+	 */
+	String SWORD_NAME = "sword";
+
+	/**
+	 * saber 系统名
+	 */
+	String SABER_NAME = "saber";
+
+	/**
+	 * 顶级父节点id
+	 */
+	Integer TOP_PARENT_ID = 0;
+
+	/**
+	 * 顶级父节点名称
+	 */
+	String TOP_PARENT_NAME = "顶级";
+
+
+	/**
+	 * 默认密码
+	 */
+	String DEFAULT_PASSWORD = "123456";
+
+	/**
+	 * 动态获取nacos地址
+	 *
+	 * @param profile 环境变量
+	 * @return addr
+	 */
+	static String nacosAddr(String profile) {
+		switch (profile) {
+			case (AppConstant.PROD_CODE):
+				return NACOS_PROD_ADDR;
+			case (AppConstant.TEST_CODE):
+				return NACOS_TEST_ADDR;
+			default:
+				return NACOS_DEV_ADDR;
+		}
+	}
+
+	/**
+	 * 动态获取sentinel地址
+	 *
+	 * @param profile 环境变量
+	 * @return addr
+	 */
+	static String sentinelAddr(String profile) {
+		switch (profile) {
+			case (AppConstant.PROD_CODE):
+				return SENTINEL_PROD_ADDR;
+			case (AppConstant.TEST_CODE):
+				return SENTINEL_TEST_ADDR;
+			default:
+				return SENTINEL_DEV_ADDR;
+		}
+	}
+
+}

+ 42 - 0
blade-common/src/main/java/org/springblade/common/launch/LauncherServiceImpl.java

@@ -0,0 +1,42 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.common.launch;
+
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.core.auto.service.AutoService;
+import org.springblade.core.launch.service.LauncherService;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+import java.util.Properties;
+
+/**
+ * 启动参数拓展
+ *
+ * @author smallchil
+ */
+@AutoService(LauncherService.class)
+public class LauncherServiceImpl implements LauncherService {
+
+	@Override
+	public void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev) {
+		Properties props = System.getProperties();
+		props.setProperty("spring.cloud.nacos.discovery.server-addr", CommonConstant.nacosAddr(profile));
+		props.setProperty("spring.cloud.nacos.config.server-addr", CommonConstant.nacosAddr(profile));
+		props.setProperty("spring.cloud.sentinel.transport.dashboard", CommonConstant.sentinelAddr(profile));
+	}
+
+}

+ 26 - 0
blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java

@@ -0,0 +1,26 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.common.utils;
+
+/**
+ * 通用工具类
+ *
+ * @author Chill
+ */
+public class CommonUtil {
+
+}

+ 8 - 0
blade-common/src/main/resources/banner.txt

@@ -0,0 +1,8 @@
+${AnsiColor.BLUE}            ______  _             _       ___   ___
+${AnsiColor.BLUE}            | ___ \| |           | |      \  \ /  /
+${AnsiColor.BLUE}            | |_/ /| |  __ _   __| |  ___  \  V  /
+${AnsiColor.BLUE}            | ___ \| | / _` | / _` | / _ \   > <
+${AnsiColor.BLUE}            | |_/ /| || (_| || (_| ||  __/ /  .  \
+${AnsiColor.BLUE}            \____/ |_| \__,_| \__,_| \___|/__/ \__\
+
+${AnsiColor.BLUE}:: BladeX :: ${spring.application.name}:${AnsiColor.RED}${blade.env}${AnsiColor.BLUE} :: Running SpringBoot ${spring-boot.version} :: ${AnsiColor.BRIGHT_BLACK}

+ 15 - 0
blade-gateway/Dockerfile

@@ -0,0 +1,15 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER smallchill@163.com
+
+RUN mkdir -p /blade/gateway
+
+WORKDIR /blade/gateway
+
+EXPOSE 80
+
+ADD ./target/blade-gateway.jar ./app.jar
+
+ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
+
+CMD ["--spring.profiles.active=test"]

+ 154 - 0
blade-gateway/pom.xml

@@ -0,0 +1,154 @@
+<?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>BladeX-Biz</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.0.0.RC9</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-gateway</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <!--Blade-->
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-launch</artifactId>
+            <version>${bladex.tool.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-web</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-undertow</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-common</artifactId>
+            <version>${bladex.project.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springblade</groupId>
+                    <artifactId>blade-core-launch</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!--Spring-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-gateway</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.codecentric</groupId>
+            <artifactId>spring-boot-admin-starter-client</artifactId>
+            <version>${spring.boot.admin.version}</version>
+        </dependency>
+        <!--Hystrix-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>commons-logging</groupId>
+                    <artifactId>commons-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!-- Nacos -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+            <version>${alibaba.cloud.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+            <version>${alibaba.cloud.version}</version>
+        </dependency>
+        <!--Swagger-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${swagger.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>io.swagger</groupId>
+                    <artifactId>swagger-models</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>${swagger.models.version}</version>
+        </dependency>
+        <!--<dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>${swagger.version}</version>
+        </dependency>-->
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>swagger-bootstrap-ui</artifactId>
+            <version>${swagger.bootstrapui.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>${docker.plugin.version}</version>
+                <configuration>
+                    <imageName>${docker.registry.url}/blade/${project.artifactId}:${project.version}</imageName>
+                    <dockerDirectory>${project.basedir}</dockerDirectory>
+                    <dockerHost>${docker.registry.host}</dockerHost>
+                    <resources>
+                        <resource>
+                            <targetPath>/</targetPath>
+                            <directory>${project.build.directory}</directory>
+                            <include>${project.build.finalName}.jar</include>
+                        </resource>
+                    </resources>
+                    <registryUrl>${docker.registry.url}</registryUrl>
+                    <serverId>${docker.registry.url}</serverId>
+                    <pushImage>true</pushImage>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                        <configuration>
+                            <tasks>
+                                <copy overwrite="true"
+                                      tofile="${session.executionRootDirectory}/target/${artifactId}.jar"
+                                      file="${project.build.directory}/${artifactId}.jar" />
+                            </tasks>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 39 - 0
blade-gateway/src/main/java/org/springblade/gateway/GateWayApplication.java

@@ -0,0 +1,39 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.gateway;
+
+import org.springblade.core.launch.constant.AppConstant;
+import org.springblade.core.launch.BladeApplication;
+import org.springframework.cloud.client.SpringCloudApplication;
+import org.springframework.cloud.netflix.hystrix.EnableHystrix;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * 项目启动
+ *
+ * @author Chill
+ */
+@EnableHystrix
+@EnableScheduling
+@SpringCloudApplication
+public class GateWayApplication {
+
+	public static void main(String[] args) {
+		BladeApplication.run(AppConstant.APPLICATION_GATEWAY_NAME, GateWayApplication.class, args);
+	}
+
+}

+ 86 - 0
blade-gateway/src/main/java/org/springblade/gateway/config/ErrorHandlerConfiguration.java

@@ -0,0 +1,86 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.gateway.config;
+
+
+import org.springblade.gateway.handler.ErrorExceptionHandler;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.web.ResourceProperties;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.web.reactive.error.ErrorAttributes;
+import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.codec.ServerCodecConfigurer;
+import org.springframework.web.reactive.result.view.ViewResolver;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 异常处理配置类
+ *
+ * @author Chill
+ */
+@Configuration
+@AutoConfigureBefore(ErrorWebFluxAutoConfiguration.class)
+@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
+public class ErrorHandlerConfiguration {
+
+	private final ServerProperties serverProperties;
+
+	private final ApplicationContext applicationContext;
+
+	private final ResourceProperties resourceProperties;
+
+	private final List<ViewResolver> viewResolvers;
+
+	private final ServerCodecConfigurer serverCodecConfigurer;
+
+	public ErrorHandlerConfiguration(ServerProperties serverProperties,
+									 ResourceProperties resourceProperties,
+									 ObjectProvider<List<ViewResolver>> viewResolversProvider,
+									 ServerCodecConfigurer serverCodecConfigurer,
+									 ApplicationContext applicationContext) {
+		this.serverProperties = serverProperties;
+		this.applicationContext = applicationContext;
+		this.resourceProperties = resourceProperties;
+		this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
+		this.serverCodecConfigurer = serverCodecConfigurer;
+	}
+
+	@Bean
+	@Order(Ordered.HIGHEST_PRECEDENCE)
+	public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
+		ErrorExceptionHandler exceptionHandler = new ErrorExceptionHandler(
+			errorAttributes,
+			this.resourceProperties,
+			this.serverProperties.getError(),
+			this.applicationContext);
+		exceptionHandler.setViewResolvers(this.viewResolvers);
+		exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
+		exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
+		return exceptionHandler;
+	}
+
+}

+ 115 - 0
blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java

@@ -0,0 +1,115 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+
+package org.springblade.gateway.config;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.gateway.handler.*;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.web.cors.reactive.CorsUtils;
+import org.springframework.web.filter.reactive.HiddenHttpMethodFilter;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import reactor.core.publisher.Mono;
+
+/**
+ * 路由配置信息
+ *
+ * @author Chill
+ */
+@Slf4j
+@Configuration
+@AllArgsConstructor
+public class RouterFunctionConfiguration {
+
+	/**
+	 * 这里为支持的请求头,如果有自定义的header字段请自己添加
+	 */
+	private static final String ALLOWED_HEADERS = "x-requested-with, blade-auth, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client";
+	private static final String ALLOWED_METHODS = "*";
+	private static final String ALLOWED_ORIGIN = "*";
+	private static final String ALLOWED_EXPOSE = "*";
+	private static final String MAX_AGE = "18000L";
+
+	private final HystrixFallbackHandler hystrixFallbackHandler;
+	private final SwaggerResourceHandler swaggerResourceHandler;
+	private final SwaggerSecurityHandler swaggerSecurityHandler;
+	private final SwaggerUiHandler swaggerUiHandler;
+
+	@Bean
+	public WebFilter corsFilter() {
+		return (ServerWebExchange ctx, WebFilterChain chain) -> {
+			ServerHttpRequest request = ctx.getRequest();
+			if (CorsUtils.isCorsRequest(request)) {
+				ServerHttpResponse response = ctx.getResponse();
+				HttpHeaders headers = response.getHeaders();
+				headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
+				headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
+				headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
+				headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
+				headers.add("Access-Control-Max-Age", MAX_AGE);
+				headers.add("Access-Control-Allow-Credentials", "true");
+				if (request.getMethod() == HttpMethod.OPTIONS) {
+					response.setStatusCode(HttpStatus.OK);
+					return Mono.empty();
+				}
+			}
+			return chain.filter(ctx);
+		};
+	}
+
+	@Bean
+	public RouterFunction routerFunction() {
+		return RouterFunctions.route(
+			RequestPredicates.path("/fallback")
+				.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), hystrixFallbackHandler)
+			.andRoute(RequestPredicates.GET("/swagger-resources")
+				.and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler)
+			.andRoute(RequestPredicates.GET("/swagger-resources/configuration/ui")
+				.and(RequestPredicates.accept(MediaType.ALL)), swaggerUiHandler)
+			.andRoute(RequestPredicates.GET("/swagger-resources/configuration/security")
+				.and(RequestPredicates.accept(MediaType.ALL)), swaggerSecurityHandler);
+
+	}
+
+	/**
+	 * 解决springboot2.0.5版本出现的 Only one connection receive subscriber allowed.
+	 * 参考:https://github.com/spring-cloud/spring-cloud-gateway/issues/541
+	 */
+	@Bean
+	public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
+		return new HiddenHttpMethodFilter() {
+			@Override
+			public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
+				return chain.filter(exchange);
+			}
+		};
+	}
+
+}

+ 58 - 0
blade-gateway/src/main/java/org/springblade/gateway/controller/DiscoveryClientController.java

@@ -0,0 +1,58 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.gateway.controller;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 服务发现控制器
+ *
+ * @author Chill
+ */
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping("/discovery")
+public class DiscoveryClientController {
+
+	private final DiscoveryClient discoveryClient;
+
+	/**
+	 * 获取服务实例
+	 */
+	@GetMapping("/instances")
+	public Map<String, List<ServiceInstance>> instances() {
+		Map<String, List<ServiceInstance>> instances = new HashMap<>(16);
+		List<String> services = discoveryClient.getServices();
+		services.forEach(s -> {
+			List<ServiceInstance> list = discoveryClient.getInstances(s);
+			instances.put(s, list);
+		});
+		return instances;
+	}
+
+}

+ 63 - 0
blade-gateway/src/main/java/org/springblade/gateway/filter/RequestGlobalFilter.java

@@ -0,0 +1,63 @@
+package org.springblade.gateway.filter;
+
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
+
+/**
+ * <p>
+ * 全局拦截器,作用所有的微服务
+ * <p>
+ * 1. 对请求头中参数进行处理 from 参数进行清洗
+ * 2. 重写StripPrefix = 1,支持全局
+ *
+ * @author lengleng
+ */
+@Component
+public class RequestGlobalFilter implements GlobalFilter, Ordered {
+
+	/**
+	 * Process the Web request and (optionally) delegate to the next
+	 * {@code WebFilter} through the given {@link GatewayFilterChain}.
+	 *
+	 * @param exchange the current server exchange
+	 * @param chain    provides a way to delegate to the next filter
+	 * @return {@code Mono<Void>} to indicate when request processing is complete
+	 */
+	@Override
+	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+		// 1. 清洗请求头中from 参数
+		ServerHttpRequest request = exchange.getRequest().mutate()
+			.headers(httpHeaders -> httpHeaders.remove("X"))
+			.build();
+
+		// 2. 重写StripPrefix
+		addOriginalRequestUrl(exchange, request.getURI());
+		String rawPath = request.getURI().getRawPath();
+		String newPath = "/" + Arrays.stream(StringUtils.tokenizeToStringArray(rawPath, "/"))
+			.skip(1L).collect(Collectors.joining("/"));
+		ServerHttpRequest newRequest = request.mutate()
+			.path(newPath)
+			.build();
+		exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI());
+
+		return chain.filter(exchange.mutate().request(newRequest.mutate().build()).build());
+	}
+
+	@Override
+	public int getOrder() {
+		return -1000;
+	}
+
+}

+ 116 - 0
blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java

@@ -0,0 +1,116 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.gateway.handler;
+
+import org.springframework.boot.autoconfigure.web.ErrorProperties;
+import org.springframework.boot.autoconfigure.web.ResourceProperties;
+import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
+import org.springframework.boot.web.reactive.error.ErrorAttributes;
+import org.springframework.cloud.gateway.support.NotFoundException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.reactive.function.server.*;
+import org.springframework.web.server.ResponseStatusException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 异常处理
+ *
+ * @author Chill
+ */
+public class ErrorExceptionHandler extends DefaultErrorWebExceptionHandler {
+
+	public ErrorExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
+								 ErrorProperties errorProperties, ApplicationContext applicationContext) {
+		super(errorAttributes, resourceProperties, errorProperties, applicationContext);
+	}
+
+	/**
+	 * 获取异常属性
+	 */
+	@Override
+	protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
+		int code = 500;
+		Throwable error = super.getError(request);
+		if (error instanceof NotFoundException) {
+			code = 404;
+		}
+		if (error instanceof ResponseStatusException) {
+			code = ((ResponseStatusException) error).getStatus().value();
+		}
+		return response(code, this.buildMessage(request, error));
+	}
+
+	/**
+	 * 指定响应处理方法为JSON处理的方法
+	 *
+	 * @param errorAttributes
+	 */
+	@Override
+	protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
+		return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
+	}
+
+	/**
+	 * 根据code获取对应的HttpStatus
+	 *
+	 * @param errorAttributes
+	 */
+	@Override
+	protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
+		int statusCode = (int) errorAttributes.get("code");
+		return HttpStatus.valueOf(statusCode);
+	}
+
+	/**
+	 * 构建异常信息
+	 *
+	 * @param request
+	 * @param ex
+	 * @return
+	 */
+	private String buildMessage(ServerRequest request, Throwable ex) {
+		StringBuilder message = new StringBuilder("Failed to handle request [");
+		message.append(request.methodName());
+		message.append(" ");
+		message.append(request.uri());
+		message.append("]");
+		if (ex != null) {
+			message.append(": ");
+			message.append(ex.getMessage());
+		}
+		return message.toString();
+	}
+
+	/**
+	 * 构建返回的JSON数据格式
+	 *
+	 * @param status       状态码
+	 * @param errorMessage 异常信息
+	 * @return
+	 */
+	public static Map<String, Object> response(int status, String errorMessage) {
+		Map<String, Object> map = new HashMap<>(16);
+		map.put("code", status);
+		map.put("message", errorMessage);
+		map.put("data", null);
+		return map;
+	}
+
+}

+ 44 - 0
blade-gateway/src/main/java/org/springblade/gateway/handler/HystrixFallbackHandler.java

@@ -0,0 +1,44 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+
+package org.springblade.gateway.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+/**
+ * Hystrix 降级处理
+ *
+ * @author lengleng
+ */
+@Slf4j
+@Component
+public class HystrixFallbackHandler implements HandlerFunction<ServerResponse> {
+	@Override
+	public Mono<ServerResponse> handle(ServerRequest serverRequest) {
+		log.error("网关执行请求:{}失败,hystrix服务降级处理", serverRequest.uri());
+		return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
+			.contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromObject("服务异常"));
+	}
+}

+ 55 - 0
blade-gateway/src/main/java/org/springblade/gateway/handler/SwaggerResourceHandler.java

@@ -0,0 +1,55 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+
+package org.springblade.gateway.handler;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+import springfox.documentation.swagger.web.SwaggerResourcesProvider;
+
+/**
+ * SwaggerResourceHandler
+ *
+ * @author lengleng
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class SwaggerResourceHandler implements HandlerFunction<ServerResponse> {
+	private final SwaggerResourcesProvider swaggerResources;
+
+	/**
+	 * Handle the given request.
+	 *
+	 * @param request the request to handler
+	 * @return the response
+	 */
+	@Override
+	public Mono<ServerResponse> handle(ServerRequest request) {
+		return ServerResponse.status(HttpStatus.OK)
+			.contentType(MediaType.APPLICATION_JSON_UTF8)
+			.body(BodyInserters.fromObject(swaggerResources.get()));
+	}
+}

+ 60 - 0
blade-gateway/src/main/java/org/springblade/gateway/handler/SwaggerSecurityHandler.java

@@ -0,0 +1,60 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+
+package org.springblade.gateway.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+import springfox.documentation.swagger.web.SecurityConfiguration;
+import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
+
+import java.util.Optional;
+
+/**
+ * SwaggerSecurityHandler
+ *
+ * @author lengleng
+ */
+@Slf4j
+@Component
+public class SwaggerSecurityHandler implements HandlerFunction<ServerResponse> {
+	@Autowired(required = false)
+	private SecurityConfiguration securityConfiguration;
+
+	/**
+	 * Handle the given request.
+	 *
+	 * @param request the request to handler
+	 * @return the response
+	 */
+	@Override
+	public Mono<ServerResponse> handle(ServerRequest request) {
+		return ServerResponse.status(HttpStatus.OK)
+			.contentType(MediaType.APPLICATION_JSON_UTF8)
+			.body(BodyInserters.fromObject(
+				Optional.ofNullable(securityConfiguration)
+					.orElse(SecurityConfigurationBuilder.builder().build())));
+	}
+}

+ 60 - 0
blade-gateway/src/main/java/org/springblade/gateway/handler/SwaggerUiHandler.java

@@ -0,0 +1,60 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+
+package org.springblade.gateway.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+import springfox.documentation.swagger.web.UiConfiguration;
+import springfox.documentation.swagger.web.UiConfigurationBuilder;
+
+import java.util.Optional;
+
+/**
+ * SwaggerUiHandler
+ *
+ * @author lengleng
+ */
+@Slf4j
+@Component
+public class SwaggerUiHandler implements HandlerFunction<ServerResponse> {
+	@Autowired(required = false)
+	private UiConfiguration uiConfiguration;
+
+	/**
+	 * Handle the given request.
+	 *
+	 * @param request the request to handler
+	 * @return the response
+	 */
+	@Override
+	public Mono<ServerResponse> handle(ServerRequest request) {
+		return ServerResponse.status(HttpStatus.OK)
+			.contentType(MediaType.APPLICATION_JSON_UTF8)
+			.body(BodyInserters.fromObject(
+				Optional.ofNullable(uiConfiguration)
+					.orElse(UiConfigurationBuilder.builder().build())));
+	}
+}

+ 78 - 0
blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java

@@ -0,0 +1,78 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+
+package org.springblade.gateway.provider;
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.launch.constant.AppConstant;
+import org.springframework.cloud.gateway.config.GatewayProperties;
+import org.springframework.cloud.gateway.route.RouteLocator;
+import org.springframework.cloud.gateway.support.NameUtils;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+import springfox.documentation.swagger.web.SwaggerResource;
+import springfox.documentation.swagger.web.SwaggerResourcesProvider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 聚合接口文档注册
+ *
+ * @author Sywd
+ */
+@Primary
+@Component
+@AllArgsConstructor
+public class SwaggerProvider implements SwaggerResourcesProvider {
+	public static final String API_URI = "/v2/api-docs-ext";
+	private final RouteLocator routeLocator;
+	private final GatewayProperties gatewayProperties;
+
+	private static Map<String, String> routeMap = new HashMap<>();
+
+	static {
+		routeMap.put(AppConstant.APPLICATION_AUTH_NAME, "授权模块");
+		routeMap.put(AppConstant.APPLICATION_DESK_NAME, "工作台模块");
+		routeMap.put(AppConstant.APPLICATION_SYSTEM_NAME, "系统模块");
+	}
+
+	@Override
+	public List<SwaggerResource> get() {
+		List<SwaggerResource> resources = new ArrayList<>();
+		List<String> routes = new ArrayList<>();
+		routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
+		gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
+			.forEach(routeDefinition -> routeDefinition.getPredicates().stream()
+				.filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName()))
+				.forEach(predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(),
+					predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
+						.replace("/**", API_URI)))));
+		return resources;
+	}
+
+	private SwaggerResource swaggerResource(String name, String location) {
+		SwaggerResource swaggerResource = new SwaggerResource();
+		swaggerResource.setName((routeMap.get(name) == null ? name : routeMap.get(name)));
+		swaggerResource.setLocation(location);
+		swaggerResource.setSwaggerVersion("2.0");
+		return swaggerResource;
+	}
+
+}

+ 25 - 0
blade-gateway/src/main/resources/bootstrap.yml

@@ -0,0 +1,25 @@
+server:
+  port: 80
+
+# 需要配置的服务名
+blade:
+  service:
+    blade-demo: blade-demo
+
+spring:
+  cloud:
+    gateway:
+      routes:
+      # demo模块
+      - id: ${blade.service.blade-demo}
+        uri: lb://${blade.service.blade-demo}
+        predicates:
+        - Path=/${blade.service.blade-demo}/**
+      discovery:
+        locator:
+          enabled: true
+    loadbalancer:
+      retry:
+        enabled: true
+
+

+ 17 - 0
blade-service-api/blade-demo-api/pom.xml

@@ -0,0 +1,17 @@
+<?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>blade-service-api</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.0.0.RC9</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-demo-api</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+</project>

+ 64 - 0
blade-service-api/blade-demo-api/src/main/java/org/springblade/demo/entity/Notice.java

@@ -0,0 +1,64 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.demo.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+import java.util.Date;
+
+/**
+ * 实体类
+ *
+ * @author Chill
+ */
+@Data
+@TableName("blade_notice")
+@EqualsAndHashCode(callSuper = true)
+public class Notice extends BaseEntity {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 标题
+	 */
+	@ApiModelProperty(value = "标题")
+	private String title;
+
+	/**
+	 * 通知类型
+	 */
+	@ApiModelProperty(value = "通知类型")
+	private Integer category;
+
+	/**
+	 * 发布日期
+	 */
+	@ApiModelProperty(value = "发布日期")
+	private Date releaseTime;
+
+	/**
+	 * 内容
+	 */
+	@ApiModelProperty(value = "内容")
+	private String content;
+
+
+}

+ 50 - 0
blade-service-api/blade-demo-api/src/main/java/org/springblade/demo/feign/INoticeClient.java

@@ -0,0 +1,50 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.demo.feign;
+
+import org.springblade.core.launch.constant.AppConstant;
+import org.springblade.core.tool.api.R;
+import org.springblade.demo.entity.Notice;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+/**
+ * Notice Feign接口类
+ *
+ * @author Chill
+ */
+@FeignClient(
+	value = AppConstant.APPLICATION_DESK_NAME
+)
+public interface INoticeClient {
+
+	String API_PREFIX = "/client";
+	String TOP = API_PREFIX + "/top";
+
+	/**
+	 * 获取notice列表
+	 *
+	 * @param number
+	 * @return
+	 */
+	@GetMapping(TOP)
+	R<List<Notice>> top(@RequestParam("number") Integer number);
+
+}

+ 20 - 0
blade-service-api/blade-demo-api/src/main/java/org/springblade/demo/vo/NoticeVO.java

@@ -0,0 +1,20 @@
+package org.springblade.demo.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.demo.entity.Notice;
+
+/**
+ * 通知公告视图类
+ *
+ * @author Chill
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class NoticeVO extends Notice {
+
+	@ApiModelProperty(value = "通知类型名")
+	private String categoryName;
+
+}

+ 82 - 0
blade-service-api/pom.xml

@@ -0,0 +1,82 @@
+<?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>BladeX-Biz</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.0.0.RC9</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-service-api</artifactId>
+    <name>${project.artifactId}</name>
+    <version>2.0.0.RC9</version>
+    <packaging>pom</packaging>
+    <description>BladeX 微服务API集合</description>
+
+    <modules>
+        <module>blade-demo-api</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-starter-mybatis</artifactId>
+            <version>${bladex.tool.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-starter-tenant</artifactId>
+            <version>${bladex.tool.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>${swagger.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>io.swagger</groupId>
+                    <artifactId>swagger-models</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>${swagger.models.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-auto</artifactId>
+            <version>${bladex.tool.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                    <finalName>${project.name}</finalName>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>${docker.plugin.version}</version>
+                <configuration>
+                    <skipDockerBuild>true</skipDockerBuild>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 15 - 0
blade-service/blade-demo/Dockerfile

@@ -0,0 +1,15 @@
+FROM anapsix/alpine-java:8_server-jre_unlimited
+
+MAINTAINER smallchill@163.com
+
+RUN mkdir -p /blade/desk
+
+WORKDIR /blade/desk
+
+EXPOSE 8105
+
+ADD ./target/blade-demo.jar ./app.jar
+
+ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
+
+CMD ["--spring.profiles.active=test"]

+ 61 - 0
blade-service/blade-demo/pom.xml

@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.springblade</groupId>
+        <artifactId>blade-service</artifactId>
+        <version>2.0.0.RC9</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-demo</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-boot</artifactId>
+            <version>${bladex.tool.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-starter-swagger</artifactId>
+            <version>${bladex.tool.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-demo-api</artifactId>
+            <version>${bladex.project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                        <configuration>
+                            <tasks>
+                                <copy overwrite="true"
+                                      tofile="${session.executionRootDirectory}/target/${artifactId}.jar"
+                                      file="${project.build.directory}/${artifactId}.jar" />
+                            </tasks>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 38 - 0
blade-service/blade-demo/src/main/java/org/springblade/demo/DemoApplication.java

@@ -0,0 +1,38 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.demo;
+
+import org.springblade.core.cloud.feign.EnableBladeFeign;
+import org.springblade.core.launch.BladeApplication;
+import org.springblade.core.launch.constant.AppConstant;
+import org.springframework.cloud.client.SpringCloudApplication;
+
+/**
+ * Demo启动器
+ *
+ * @author Chill
+ */
+@EnableBladeFeign
+@SpringCloudApplication
+public class DemoApplication {
+
+	public static void main(String[] args) {
+		BladeApplication.run(AppConstant.APPLICATION_DEMO_NAME, DemoApplication.class, args);
+	}
+
+}
+

+ 109 - 0
blade-service/blade-demo/src/main/java/org/springblade/demo/controller/NoticeController.java

@@ -0,0 +1,109 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.demo.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.common.cache.CacheNames;
+import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.demo.entity.Notice;
+import org.springblade.demo.service.INoticeService;
+import org.springframework.web.bind.annotation.*;
+import springfox.documentation.annotations.ApiIgnore;
+
+import java.util.Map;
+
+/**
+ * 控制器
+ *
+ * @author Chill
+ */
+@RestController
+@RequestMapping("notice")
+@AllArgsConstructor
+@Api(value = "用户博客", tags = "博客接口")
+public class NoticeController extends BladeController implements CacheNames {
+
+	private INoticeService noticeService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperation(value = "详情", notes = "传入notice", position = 2)
+	public R<Notice> detail(Notice notice) {
+		Notice detail = noticeService.getOne(Condition.getQueryWrapper(notice));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页
+	 */
+	@GetMapping("/list")
+	@ApiImplicitParams({
+		@ApiImplicitParam(name = "category", value = "公告类型", paramType = "query", dataType = "integer"),
+		@ApiImplicitParam(name = "title", value = "公告标题", paramType = "query", dataType = "string")
+	})
+	@ApiOperation(value = "分页", notes = "传入notice", position = 3)
+	public R<IPage<Notice>> list(@ApiIgnore @RequestParam Map<String, Object> notice, Query query) {
+		IPage<Notice> pages = noticeService.page(Condition.getPage(query), Condition.getQueryWrapper(notice, Notice.class));
+		return R.data(pages);
+	}
+
+	/**
+	 * 新增
+	 */
+	@PostMapping("/save")
+	@ApiOperation(value = "新增", notes = "传入notice", position = 4)
+	public R save(@RequestBody Notice notice) {
+		return R.status(noticeService.save(notice));
+	}
+
+	/**
+	 * 修改
+	 */
+	@PostMapping("/update")
+	@ApiOperation(value = "修改", notes = "传入notice", position = 5)
+	public R update(@RequestBody Notice notice) {
+		return R.status(noticeService.updateById(notice));
+	}
+
+	/**
+	 * 新增或修改
+	 */
+	@PostMapping("/submit")
+	@ApiOperation(value = "新增或修改", notes = "传入notice", position = 6)
+	public R submit(@RequestBody Notice notice) {
+		return R.status(noticeService.saveOrUpdate(notice));
+	}
+
+	/**
+	 * 删除
+	 */
+	@PostMapping("/remove")
+	@ApiOperation(value = "逻辑删除", notes = "传入notice", position = 7)
+	public R remove(@ApiParam(value = "主键集合") @RequestParam String ids) {
+		boolean temp = noticeService.deleteLogic(Func.toIntList(ids));
+		return R.status(temp);
+	}
+
+}

+ 47 - 0
blade-service/blade-demo/src/main/java/org/springblade/demo/feign/NoticeClient.java

@@ -0,0 +1,47 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.demo.feign;
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.tool.api.R;
+import org.springblade.demo.mapper.NoticeMapper;
+import org.springblade.demo.entity.Notice;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import springfox.documentation.annotations.ApiIgnore;
+
+import java.util.List;
+
+/**
+ * Notice Feign
+ *
+ * @author Chill
+ */
+@ApiIgnore()
+@RestController
+@AllArgsConstructor
+public class NoticeClient implements INoticeClient {
+
+	NoticeMapper mapper;
+
+	@Override
+	@GetMapping(TOP)
+	public R<List<Notice>> top(Integer number) {
+		return R.data(mapper.topList(number));
+	}
+
+}

+ 47 - 0
blade-service/blade-demo/src/main/java/org/springblade/demo/mapper/NoticeMapper.java

@@ -0,0 +1,47 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.demo.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.demo.entity.Notice;
+
+import java.util.List;
+
+/**
+ * Mapper 接口
+ *
+ * @author Chill
+ */
+public interface NoticeMapper extends BaseMapper<Notice> {
+
+	/**
+	 * 前N条数据
+	 * @param number
+	 * @return
+	 */
+	List<Notice> topList(Integer number);
+
+	/**
+	 * 自定义分页
+	 * @param page
+	 * @param notice
+	 * @return
+	 */
+	List<Notice> selectNoticePage(IPage page, Notice notice);
+
+}

+ 39 - 0
blade-service/blade-demo/src/main/java/org/springblade/demo/mapper/NoticeMapper.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.demo.mapper.NoticeMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="noticeResultMap" type="org.springblade.demo.entity.Notice">
+        <result column="id" property="id"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="release_time" property="releaseTime"/>
+        <result column="title" property="title"/>
+        <result column="content" property="content"/>
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="baseColumnList">
+        select id,
+        create_user AS createUser,
+        create_time AS createTime,
+        update_user AS updateUser,
+        update_time AS updateTime,
+        status,
+        is_deleted AS isDeleted,
+        title, content
+    </sql>
+
+    <select id="topList" resultMap="noticeResultMap">
+        select * from blade_notice limit #{number}
+    </select>
+
+    <select id="selectNoticePage" resultMap="noticeResultMap">
+        select * from blade_notice where title like concat('%', #{notice.title}, '%') and is_deleted = 0
+    </select>
+
+</mapper>

+ 38 - 0
blade-service/blade-demo/src/main/java/org/springblade/demo/service/INoticeService.java

@@ -0,0 +1,38 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.demo.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.demo.entity.Notice;
+
+/**
+ * 服务类
+ *
+ * @author Chill
+ */
+public interface INoticeService extends BaseService<Notice> {
+
+	/**
+	 * 自定义分页
+	 * @param page
+	 * @param notice
+	 * @return
+	 */
+	IPage<Notice> selectNoticePage(IPage<Notice> page, Notice notice);
+
+}

+ 39 - 0
blade-service/blade-demo/src/main/java/org/springblade/demo/service/impl/NoticeServiceImpl.java

@@ -0,0 +1,39 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.demo.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.demo.entity.Notice;
+import org.springblade.demo.mapper.NoticeMapper;
+import org.springblade.demo.service.INoticeService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 服务实现类
+ *
+ * @author Chill
+ */
+@Service
+public class NoticeServiceImpl extends BaseServiceImpl<NoticeMapper, Notice> implements INoticeService {
+
+	@Override
+	public IPage<Notice> selectNoticePage(IPage<Notice> page, Notice notice) {
+		return page.setRecords(baseMapper.selectNoticePage(page, notice));
+	}
+
+}

+ 10 - 0
blade-service/blade-demo/src/main/resources/application-dev.yml

@@ -0,0 +1,10 @@
+#服务器端口
+server:
+  port: 8200
+
+#数据源配置
+spring:
+  datasource:
+    url: ${blade.datasource.dev.url}
+    username: ${blade.datasource.dev.username}
+    password: ${blade.datasource.dev.password}

+ 10 - 0
blade-service/blade-demo/src/main/resources/application-prod.yml

@@ -0,0 +1,10 @@
+#服务器端口
+server:
+  port: 8200
+
+#数据源配置
+spring:
+  datasource:
+    url: ${blade.datasource.prod.url}
+    username: ${blade.datasource.prod.username}
+    password: ${blade.datasource.prod.password}

+ 10 - 0
blade-service/blade-demo/src/main/resources/application-test.yml

@@ -0,0 +1,10 @@
+#服务器端口
+server:
+  port: 8200
+
+#数据源配置
+spring:
+  datasource:
+    url: ${blade.datasource.test.url}
+    username: ${blade.datasource.test.username}
+    password: ${blade.datasource.test.password}

+ 61 - 0
blade-service/pom.xml

@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<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>
+
+    <artifactId>blade-service</artifactId>
+    <name>${project.artifactId}</name>
+    <version>2.0.0.RC9</version>
+    <packaging>pom</packaging>
+    <description>BladeX 微服务集合</description>
+
+    <parent>
+        <groupId>org.springblade</groupId>
+        <artifactId>BladeX-Biz</artifactId>
+        <version>2.0.0.RC9</version>
+    </parent>
+
+    <modules>
+        <module>blade-demo</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-common</artifactId>
+            <version>${bladex.project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-starter-tenant</artifactId>
+            <version>${bladex.tool.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <version>${docker.plugin.version}</version>
+                <configuration>
+                    <imageName>${docker.registry.url}/blade/${project.artifactId}:${project.version}</imageName>
+                    <dockerDirectory>${project.basedir}</dockerDirectory>
+                    <dockerHost>${docker.registry.host}</dockerHost>
+                    <resources>
+                        <resource>
+                            <targetPath>/</targetPath>
+                            <directory>${project.build.directory}</directory>
+                            <include>${project.build.finalName}.jar</include>
+                        </resource>
+                    </resources>
+                    <registryUrl>${docker.registry.url}</registryUrl>
+                    <serverId>${docker.registry.url}</serverId>
+                    <pushImage>true</pushImage>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 160 - 0
pom.xml

@@ -0,0 +1,160 @@
+<?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>org.springblade</groupId>
+    <artifactId>BladeX-Biz</artifactId>
+    <version>2.0.0.RC9</version>
+    <packaging>pom</packaging>
+
+    <properties>
+        <bladex.tool.version>2.0.0.RC9</bladex.tool.version>
+        <bladex.project.version>2.0.0.RC9</bladex.project.version>
+
+        <java.version>1.8</java.version>
+        <swagger.version>2.9.2</swagger.version>
+        <swagger.models.version>1.5.21</swagger.models.version>
+        <swagger.bootstrapui.version>1.9.3</swagger.bootstrapui.version>
+        <mybatis.plus.version>3.1.0</mybatis.plus.version>
+        <curator.framework.version>4.0.1</curator.framework.version>
+        <protostuff.version>1.6.0</protostuff.version>
+        <flowable.version>6.4.1</flowable.version>
+        <spring.boot.admin.version>2.1.4</spring.boot.admin.version>
+
+        <alibaba.cloud.version>0.9.0.RELEASE</alibaba.cloud.version>
+
+        <spring.boot.version>2.1.4.RELEASE</spring.boot.version>
+        <spring.cloud.version>Greenwich.SR1</spring.cloud.version>
+        <spring.platform.version>Cairo-SR7</spring.platform.version>
+
+        <!-- 推荐使用Harbor -->
+        <docker.registry.url>192.168.0.157</docker.registry.url>
+        <docker.registry.host>http://${docker.registry.url}:2375</docker.registry.host>
+        <docker.plugin.version>1.2.0</docker.plugin.version>
+    </properties>
+
+    <modules>
+        <module>blade-common</module>
+        <module>blade-gateway</module>
+        <module>blade-service</module>
+        <module>blade-service-api</module>
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring.boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.cloud</groupId>
+                <artifactId>spring-cloud-dependencies</artifactId>
+                <version>${spring.cloud.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>io.spring.platform</groupId>
+                <artifactId>platform-bom</artifactId>
+                <version>${spring.platform.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.name}</finalName>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+            <resource>
+                <directory>src/main/java</directory>
+                <includes>
+                    <include>**/*.xml</include>
+                </includes>
+            </resource>
+        </resources>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-maven-plugin</artifactId>
+                    <version>${spring.boot.version}</version>
+                    <configuration>
+                        <fork>true</fork>
+                        <finalName>${project.build.finalName}</finalName>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <goals>
+                                <goal>repackage</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${java.version}</source>
+                    <target>${java.version}</target>
+                    <encoding>UTF-8</encoding>
+                    <compilerArgs>
+                        <arg>-parameters</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <repositories>
+        <repository>
+            <id>release</id>
+            <name>Release Repository</name>
+            <url>http://nexus.gitee.ltd/repository/maven-releases/</url>
+        </repository>
+        <repository>
+            <id>aliyun-repos</id>
+            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>aliyun-plugin</id>
+            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+</project>

+ 2 - 0
script/docker/.env

@@ -0,0 +1,2 @@
+REGISTER=192.168.0.157/blade
+TAG=2.0.0.RC9

+ 96 - 0
script/docker/deploy.sh

@@ -0,0 +1,96 @@
+
+#使用说明,用来提示输入参数
+usage() {
+	echo "Usage: sh 执行脚本.sh [port|mount|base|modules|monitor|stop|rm|rmiNoneTag]"
+	exit 1
+}
+
+#开启所需端口
+port(){
+	firewall-cmd --add-port=88/tcp --permanent
+	firewall-cmd --add-port=8000/tcp --permanent
+	firewall-cmd --add-port=8848/tcp --permanent
+	firewall-cmd --add-port=8858/tcp --permanent
+	firewall-cmd --add-port=3306/tcp --permanent
+	firewall-cmd --add-port=3379/tcp --permanent
+	firewall-cmd --add-port=7002/tcp --permanent
+	service firewalld restart
+}
+
+##放置挂载文件
+mount(){
+	if test ! -f "/docker/nginx/api/nginx.conf" ;then
+		mkdir -p /docker/nginx/api
+		cp nginx/api/nginx.conf /docker/nginx/api/nginx.conf
+	fi
+	if test ! -f "/docker/nginx/web/nginx.conf" ;then
+		mkdir -p /docker/nginx/web
+		cp nginx/web/nginx.conf /docker/nginx/web/nginx.conf
+		cp -r nginx/web/html /docker/nginx/web/html
+	fi
+	if test ! -f "/docker/nacos/init.d/custom.properties" ;then
+		mkdir -p /docker/nacos/init.d
+		cp nacos/init.d/custom.properties /docker/nacos/init.d/custom.properties
+	fi
+}
+
+#启动基础模块
+base(){
+	docker-compose up -d nacos sentinel web-nginx blade-nginx blade-redis
+}
+
+#启动程序模块
+modules(){
+	docker-compose up -d blade-gateway1 blade-gateway2 blade-auth1 blade-auth2 blade-user blade-desk blade-system blade-log
+}
+
+#启动监控模块
+monitor(){
+	docker-compose up -d blade-admin
+}
+
+#关闭所有模块
+stop(){
+	docker-compose stop
+}
+
+#删除所有模块
+rm(){
+	docker-compose rm
+}
+
+#删除Tag为空的镜像
+rmiNoneTag(){
+	docker images|grep none|awk '{print $3}'|xargs docker rmi -f
+}
+
+#根据输入参数,选择执行对应方法,不输入则执行使用说明
+case "$1" in
+"port")
+	port
+;;
+"mount")
+	mount
+;;
+"base")
+	base
+;;
+"modules")
+	modules
+;;
+"monitor")
+	monitor
+;;
+"stop")
+	stop
+;;
+"rm")
+	rm
+;;
+"rmiNoneTag")
+	rmiNoneTag
+;;
+*)
+	usage
+;;
+esac

+ 139 - 0
script/docker/docker-compose.yml

@@ -0,0 +1,139 @@
+version: '3'
+services:
+  nacos:
+    image: nacos/nacos-server:0.9.0
+    hostname: "nacos-standalone"
+    environment:
+      - MODE=standalone
+    volumes:
+      - /docker/nacos/standalone-logs/:/home/nacos/logs
+      - /docker/nacos/init.d/custom.properties:/home/nacos/init.d/custom.properties
+    ports:
+      - 8848:8848
+    networks:
+      blade_net:
+        ipv4_address: 172.30.0.48
+
+  sentinel:
+    image: bladex/sentinel-dashboard:1.5.0
+    hostname: "sentinel"
+    ports:
+      - 8858:8858
+    restart: on-failure
+    networks:
+      blade_net:
+        ipv4_address: 172.30.0.58
+
+  blade-nginx:
+    image: nginx:stable-alpine-perl
+    hostname: "blade-nginx"
+    ports:
+    - 88:88
+    volumes:
+    - /docker/nginx/gateway/nginx.conf:/etc/nginx/nginx.conf
+    privileged: true
+    restart: always
+    networks:
+    - blade_net
+
+  web-nginx:
+    image: nginx:stable-alpine-perl
+    hostname: "web-nginx"
+    ports:
+      - 8000:8000
+    volumes:
+      - /docker/nginx/web/html:/usr/share/nginx/html
+      - /docker/nginx/web/nginx.conf:/etc/nginx/nginx.conf
+    privileged: true
+    restart: always
+    networks:
+      - blade_net
+
+  blade-redis:
+    image: redis:5.0.2-alpine
+    hostname: "blade-redis"
+    ports:
+    - 3379:6379
+    volumes:
+    - /docker/redis/data:/data
+    command: "redis-server --appendonly yes"
+    privileged: true
+    restart: always
+    networks:
+    - blade_net
+
+  blade-admin:
+    image: "${REGISTER}/blade/blade-admin:${TAG}"
+    ports:
+    - 7002:7002
+    privileged: true
+    restart: always
+    networks:
+    - blade_net
+
+  blade-gateway1:
+    image: "${REGISTER}/blade/blade-gateway:${TAG}"
+    privileged: true
+    restart: always
+    networks:
+      blade_net:
+        ipv4_address: 172.30.0.81
+
+  blade-gateway2:
+    image: "${REGISTER}/blade/blade-gateway:${TAG}"
+    privileged: true
+    restart: always
+    networks:
+      blade_net:
+        ipv4_address: 172.30.0.82
+
+  blade-auth1:
+    image: "${REGISTER}/blade/blade-auth:${TAG}"
+    privileged: true
+    restart: always
+    networks:
+      blade_net:
+        ipv4_address: 172.30.0.91
+
+  blade-auth2:
+    image: "${REGISTER}/blade/blade-auth:${TAG}"
+    privileged: true
+    restart: always
+    networks:
+      blade_net:
+        ipv4_address: 172.30.0.92
+
+  blade-log:
+    image: "${REGISTER}/blade/blade-log:${TAG}"
+    privileged: true
+    restart: always
+    networks:
+    - blade_net
+
+  blade-desk:
+    image: "${REGISTER}/blade/blade-desk:${TAG}"
+    privileged: true
+    restart: always
+    networks:
+    - blade_net
+
+  blade-user:
+    image: "${REGISTER}/blade/blade-user:${TAG}"
+    privileged: true
+    restart: always
+    networks:
+    - blade_net
+
+  blade-system:
+    image: "${REGISTER}/blade/blade-system:${TAG}"
+    privileged: true
+    restart: always
+    networks:
+    - blade_net
+
+networks:
+  blade_net:
+    driver: bridge
+    ipam:
+      config:
+      - subnet: 172.30.0.0/16

+ 19 - 0
script/docker/nacos/init.d/custom.properties

@@ -0,0 +1,19 @@
+#spring.security.enabled=false
+#management.security=false
+#security.basic.enabled=false
+#nacos.security.ignore.urls=/**
+#management.metrics.export.elastic.host=http://localhost:9200
+# metrics for prometheus
+management.endpoints.web.exposure.include=*
+
+# metrics for elastic search
+#management.metrics.export.elastic.enabled=false
+#management.metrics.export.elastic.host=http://localhost:9200
+
+# metrics for influx
+#management.metrics.export.influx.enabled=false
+#management.metrics.export.influx.db=springboot
+#management.metrics.export.influx.uri=http://localhost:8086
+#management.metrics.export.influx.auto-create-db=true
+#management.metrics.export.influx.consistency=one
+#management.metrics.export.influx.compressed=true

+ 67 - 0
script/docker/nginx/api/nginx.conf

@@ -0,0 +1,67 @@
+
+user  root;
+worker_processes  1;
+
+error_log  /var/log/nginx/error.log warn;
+pid        /var/run/nginx.pid;
+
+
+events {
+    worker_connections  1024;
+}
+
+
+http {
+    include       /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+
+    access_log  /var/log/nginx/access.log  main;
+
+    sendfile        on;
+    #tcp_nopush     on;
+
+    keepalive_timeout  65;
+
+    #gzip  on;
+
+    #include /etc/nginx/conf.d/*.conf;
+
+    upstream gateway {
+                 server 172.30.0.81;
+                 server 172.30.0.82;
+             }
+
+    upstream auth {
+                 server 172.30.0.91;
+                 server 172.30.0.92;
+             }
+
+    server {
+      listen       88;
+      server_name  gateway;
+      location / {
+           proxy_set_header Host $host;
+           proxy_set_header X-Real-IP $remote_addr;
+           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+           proxy_buffering off;
+           proxy_pass http://gateway;
+      }
+    }
+
+    server {
+      listen       9000;
+      server_name  auth;
+      location / {
+           proxy_set_header Host $host;
+           proxy_set_header X-Real-IP $remote_addr;
+           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+           proxy_buffering off;
+           proxy_pass http://auth;
+      }
+    }
+
+}

+ 10 - 0
script/docker/nginx/web/html/index.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Hello BladeX</title>
+</head>
+<body>
+<div style="text-align: center">Hello BladeX !</div>
+</body>
+</html>

+ 60 - 0
script/docker/nginx/web/nginx.conf

@@ -0,0 +1,60 @@
+
+user  root;
+worker_processes  1;
+
+error_log  /var/log/nginx/error.log warn;
+pid        /var/run/nginx.pid;
+
+
+events {
+    worker_connections  1024;
+}
+
+
+http {
+    include       /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+
+    access_log  /var/log/nginx/access.log  main;
+
+    sendfile        on;
+    #tcp_nopush     on;
+
+    keepalive_timeout  65;
+
+    #gzip  on;
+
+    #include /etc/nginx/conf.d/*.conf;
+
+    upstream gateway {
+                 server 172.30.0.81;
+                 server 172.30.0.82;
+                 server 172.30.0.83;
+             }
+
+
+    server {
+      listen       8000;
+      server_name  web;
+      root         /usr/share/nginx/html;
+
+      location / {
+
+      }
+
+      location ^~/api {
+           proxy_set_header Host $host;
+           proxy_set_header X-Real-IP $remote_addr;
+           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+           proxy_buffering off;
+           rewrite ^/api/(.*)$ /$1 break;
+           proxy_pass http://gateway;
+      }
+    }
+
+
+}

+ 1 - 0
script/service.cmd

@@ -0,0 +1 @@
+java -jar app.jar

+ 73 - 0
script/service.sh

@@ -0,0 +1,73 @@
+APP_NAME=app.jar
+
+#使用说明,用来提示输入参数
+usage() {
+echo "Usage: sh 执行脚本.sh [start|stop|restart|status]"
+exit 1
+}
+
+#检查程序是否在运行
+is_exist(){
+pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}' `
+#如果不存在返回1,存在返回0
+if [ -z "${pid}" ]; then
+return 1
+else
+return 0
+fi
+}
+
+#启动方法
+start(){
+is_exist
+if [ $? -eq "0" ]; then
+echo "${APP_NAME} is already running. pid=${pid} ."
+else
+nohup java -jar $APP_NAME > /dev/null 2>&1 &
+fi
+}
+
+#停止方法
+stop(){
+is_exist
+if [ $? -eq "0" ]; then
+kill -9 $pid
+else
+echo "${APP_NAME} is not running"
+fi
+}
+
+#输出运行状态
+status(){
+is_exist
+if [ $? -eq "0" ]; then
+echo "${APP_NAME} is running. Pid is ${pid}"
+else
+echo "${APP_NAME} is NOT running."
+fi
+}
+
+#重启
+restart(){
+stop
+start
+}
+
+#根据输入参数,选择执行对应方法,不输入则执行使用说明
+case "$1" in
+"start")
+start
+;;
+"stop")
+stop
+;;
+"status")
+status
+;;
+"restart")
+restart
+;;
+*)
+usage
+;;
+esac