commit
b64539515e
@ -1,29 +1,31 @@ |
||||
* [首页](/?t=1561689549009) |
||||
* [首页](/?t=1561975674071) |
||||
* 开发文档 |
||||
* [快速体验](files/10010_快速体验.md?t=1561689549011) |
||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561689549027) |
||||
* [新增接口](files/10020_新增接口.md?t=1561689549027) |
||||
* [业务参数校验](files/10030_业务参数校验.md?t=1561689549028) |
||||
* [错误处理](files/10040_错误处理.md?t=1561689549028) |
||||
* [编写文档](files/10041_编写文档.md?t=1561689549028) |
||||
* [接口交互详解](files/10050_接口交互详解.md?t=1561689549028) |
||||
* [easyopen支持](files/10070_easyopen支持.md?t=1561689549028) |
||||
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561689549028) |
||||
* [ISV管理](files/10085_ISV管理.md?t=1561689549028) |
||||
* [自定义路由](files/10086_自定义路由.md?t=1561689549028) |
||||
* [路由授权](files/10090_路由授权.md?t=1561689549028) |
||||
* [接口限流](files/10092_接口限流.md?t=1561689549029) |
||||
* [监控日志](files/10093_监控日志.md?t=1561689549029) |
||||
* [SDK开发](files/10095_SDK开发.md?t=1561689549029) |
||||
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561689549029) |
||||
* [应用授权](files/10097_应用授权.md?t=1561689549029) |
||||
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561689549029) |
||||
* [对接前端](files/10100_对接前端.md?t=1561689549029) |
||||
* [自定义过滤器](files/10102_自定义过滤器.md?t=1561689549029) |
||||
* [文件上传](files/10104_文件上传.md?t=1561689549029) |
||||
* [快速体验](files/10010_快速体验.md?t=1561975674073) |
||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1561975674089) |
||||
* [新增接口](files/10020_新增接口.md?t=1561975674089) |
||||
* [业务参数校验](files/10030_业务参数校验.md?t=1561975674090) |
||||
* [错误处理](files/10040_错误处理.md?t=1561975674090) |
||||
* [编写文档](files/10041_编写文档.md?t=1561975674090) |
||||
* [接口交互详解](files/10050_接口交互详解.md?t=1561975674090) |
||||
* [easyopen支持](files/10070_easyopen支持.md?t=1561975674090) |
||||
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1561975674090) |
||||
* [ISV管理](files/10085_ISV管理.md?t=1561975674090) |
||||
* [自定义路由](files/10086_自定义路由.md?t=1561975674090) |
||||
* [路由授权](files/10090_路由授权.md?t=1561975674090) |
||||
* [接口限流](files/10092_接口限流.md?t=1561975674090) |
||||
* [监控日志](files/10093_监控日志.md?t=1561975674091) |
||||
* [SDK开发](files/10095_SDK开发.md?t=1561975674091) |
||||
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1561975674091) |
||||
* [应用授权](files/10097_应用授权.md?t=1561975674091) |
||||
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1561975674091) |
||||
* [对接前端](files/10100_对接前端.md?t=1561975674091) |
||||
* [自定义过滤器](files/10102_自定义过滤器.md?t=1561975674091) |
||||
* [文件上传](files/10104_文件上传.md?t=1561975674091) |
||||
* [nacos注册中心](files/10106_nacos注册中心.md?t=1561975674091) |
||||
* [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1561975674091) |
||||
* 原理分析 |
||||
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561689549029) |
||||
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561689549030) |
||||
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561689549030) |
||||
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561689549030) |
||||
* [常见问题](files/90100_常见问题.md?t=1561689549030) |
||||
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1561975674092) |
||||
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1561975674092) |
||||
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1561975674092) |
||||
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1561975674092) |
||||
* [常见问题](files/90100_常见问题.md?t=1561975674092) |
||||
|
@ -0,0 +1,88 @@ |
||||
# nacos注册中心 |
||||
|
||||
使用nacos作为注册中心,步骤如下: |
||||
|
||||
- 准备工作 |
||||
|
||||
1.安装nacos,前往[最新稳定版本](https://github.com/alibaba/nacos/releases),下载最新版nacos |
||||
|
||||
2.启动nacos服务器,cd nacos/bin |
||||
|
||||
Linux/Unix/Mac,启动命令(standalone代表着单机模式运行,非集群模式): |
||||
|
||||
`sh startup.sh -m standalone` |
||||
|
||||
Windows,启动命令: |
||||
|
||||
`cmd startup.cmd` |
||||
|
||||
或者双击startup.cmd运行文件。 |
||||
|
||||
更多访问:https://nacos.io/zh-cn/docs/quick-start.html |
||||
|
||||
- 微服务端修改 |
||||
|
||||
1.修改微服务应用pom,打开`sop-example/sop-story/sop-story-web/pom.xml`,注释eureka服务发现依赖,添加nacos服务发现依赖 |
||||
|
||||
```xml |
||||
<!-- 注册中心【只能用一个,不用的注释掉】 --> |
||||
<!-- 使用eureka注册中心 |
||||
<dependency> |
||||
<groupId>org.springframework.cloud</groupId> |
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> |
||||
</dependency> |
||||
--> |
||||
|
||||
<!-- 使用nacos注册中心 |
||||
版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。 |
||||
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery |
||||
--> |
||||
<dependency> |
||||
<groupId>org.springframework.cloud</groupId> |
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> |
||||
<version>0.2.2.RELEASE</version> |
||||
</dependency> |
||||
<!-- 注册中心end --> |
||||
``` |
||||
|
||||
2.yml文件新增nacos配置,并注释掉eureka相关配置 |
||||
|
||||
```yaml |
||||
spring: |
||||
cloud: |
||||
# nacos注册中心,和eureka只能用一个 |
||||
nacos: |
||||
discovery: |
||||
server-addr: 127.0.0.1:8848 |
||||
``` |
||||
|
||||
- 网关修改 |
||||
|
||||
找到`sop-gateway`工程,步骤同上 |
||||
|
||||
- SOP-admin修改 |
||||
|
||||
|
||||
修改yml文件,设置nacos服务器地址,`registry.name`填nacos |
||||
|
||||
```yaml |
||||
# 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 |
||||
registry: |
||||
eureka-server-addr: http://localhost:1111/eureka/ |
||||
# nacos服务器地址 |
||||
nacos-server-addr: 127.0.0.1:8848 |
||||
# 使用eureka,填:eureka,使用nacos填:nacos |
||||
name: nacos |
||||
``` |
||||
|
||||
- website-server修改 |
||||
|
||||
步骤同`SOP-admin修改` |
||||
|
||||
如果要改成consul注册中心,可参照以上步骤。 |
||||
|
||||
- 参考资料 |
||||
|
||||
1.[nacos介绍及安装](https://nacos.io/zh-cn/docs/quick-start.html) |
||||
|
||||
2.[nacos spring cloud注册发现](https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html) |
@ -0,0 +1,112 @@ |
||||
# 扩展其它注册中心 |
||||
|
||||
**注: nacos注册中心已经实现,本篇以nacos为例介绍如何扩展,如果要改成consul,可按照此方式进行修改** |
||||
|
||||
SOP默认使用eureka注册中心,如果要换成nacos注册中心,步骤如下: |
||||
|
||||
- 实现`com.gitee.sop.registryapi.service.RegistryService`接口 |
||||
|
||||
1.找到`SOP/sop-common/sop-registry-api`工程,在service.impl包下新建一个类,实现RegistryService接口 |
||||
|
||||
```java |
||||
public class RegistryServiceNacos implements RegistryService { |
||||
|
||||
@Override |
||||
public List<ServiceInfo> listAllService(int pageNo, int pageSize) throws Exception { |
||||
// TODO: 返回服务实例 |
||||
} |
||||
|
||||
@Override |
||||
public void onlineInstance(ServiceInstance serviceInstance) throws Exception { |
||||
// TODO: 实例上线 |
||||
} |
||||
|
||||
@Override |
||||
public void offlineInstance(ServiceInstance serviceInstance) throws Exception { |
||||
// TODO: 实例下线 |
||||
} |
||||
} |
||||
``` |
||||
|
||||
2.在`com.gitee.sop.registryapi.config.BaseRegistryConfig`中新增 |
||||
|
||||
```java |
||||
/** |
||||
* 当配置了registry.name=nacos生效 |
||||
* |
||||
* @return |
||||
*/ |
||||
@Bean |
||||
@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos") |
||||
RegistryService registryServiceNacos() { |
||||
return new RegistryServiceNacos(); |
||||
} |
||||
``` |
||||
|
||||
其中`@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos")` |
||||
表示`application.properties`配置了`registry.name=nacos`参数才能生效,registry.name=nacos下文会讲到。 |
||||
|
||||
|
||||
- 微服务端修改 |
||||
|
||||
1.修改微服务应用pom.xml,注释eureka服务发现依赖,添加nacos服务发现依赖 |
||||
|
||||
```xml |
||||
<!-- 注册中心【只能用一个,不用的注释掉】 --> |
||||
<!-- 使用eureka注册中心 |
||||
<dependency> |
||||
<groupId>org.springframework.cloud</groupId> |
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> |
||||
</dependency> |
||||
--> |
||||
|
||||
<!-- 使用nacos注册中心 |
||||
版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。 |
||||
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-discovery |
||||
--> |
||||
<dependency> |
||||
<groupId>org.springframework.cloud</groupId> |
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> |
||||
<version>0.2.2.RELEASE</version> |
||||
</dependency> |
||||
<!-- 注册中心end --> |
||||
``` |
||||
|
||||
2.yml文件新增nacos配置,并注释掉eureka相关配置 |
||||
|
||||
```yaml |
||||
spring: |
||||
cloud: |
||||
# nacos注册中心,和eureka只能用一个 |
||||
nacos: |
||||
discovery: |
||||
server-addr: 127.0.0.1:8848 |
||||
``` |
||||
|
||||
- 网关修改 |
||||
|
||||
找到`sop-gateway`工程,步骤同上 |
||||
|
||||
- SOP-admin修改 |
||||
|
||||
|
||||
修改yml文件,新增nacos服务器地址,`registry.name`填nacos |
||||
|
||||
```yaml |
||||
# 注册中心地址,根据实际情况改,这里只是参数,并不会去注册 |
||||
registry: |
||||
# 使用eureka,填:eureka,使用nacos填:nacos |
||||
name: nacos |
||||
eureka-server-addr: http://localhost:1111/eureka/ |
||||
nacos-server-addr: 127.0.0.1:8848 |
||||
``` |
||||
|
||||
- website-server修改 |
||||
|
||||
步骤同`SOP-admin修改` |
||||
|
||||
- 参考资料 |
||||
|
||||
1.[nacos介绍及安装](https://nacos.io/zh-cn/docs/quick-start.html) |
||||
|
||||
2.[nacos spring cloud注册发现](https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html) |
@ -1,5 +1,5 @@ |
||||
# 后台admin |
||||
|
||||
- sop-admin-front: admin前端layui实现(停止维护) |
||||
- sop-admin-front: admin前端layui实现(停止维护,改用sop-admin-vue) |
||||
- sop-admin-server: admin服务端 |
||||
- sop-admin-vue: admin前端vue实现 |
||||
|
@ -0,0 +1,24 @@ |
||||
package com.gitee.sop.adminserver.api.isv.param; |
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||
import lombok.Data; |
||||
import org.hibernate.validator.constraints.Length; |
||||
|
||||
import javax.validation.constraints.NotBlank; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Data |
||||
public class RoleForm { |
||||
@ApiDocField(description = "id") |
||||
private Long id; |
||||
|
||||
@ApiDocField(description = "角色码") |
||||
@NotBlank(message = "roleCode不能为空") |
||||
@Length(max = 64) |
||||
private String roleCode; |
||||
|
||||
@ApiDocField(description = "描述") |
||||
private String description; |
||||
} |
@ -0,0 +1,19 @@ |
||||
package com.gitee.sop.adminserver.api.isv.param; |
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||
import com.gitee.fastmybatis.core.query.Operator; |
||||
import com.gitee.fastmybatis.core.query.annotation.Condition; |
||||
import com.gitee.fastmybatis.core.query.param.PageParam; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Getter |
||||
@Setter |
||||
public class RolePageParam extends PageParam { |
||||
@ApiDocField(description = "角色码") |
||||
@Condition(operator = Operator.like) |
||||
private String roleCode; |
||||
} |
@ -0,0 +1,54 @@ |
||||
package com.gitee.sop.adminserver.api.service.result; |
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField; |
||||
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||
import lombok.Data; |
||||
import org.apache.commons.lang.StringUtils; |
||||
|
||||
import java.util.Date; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Data |
||||
public class ServiceInstanceVO { |
||||
@ApiDocField(description = "id") |
||||
private Integer id; |
||||
|
||||
@ApiDocField(description = "服务名称(serviceId)") |
||||
private String serviceId; |
||||
|
||||
@ApiDocField(description = "instanceId") |
||||
private String instanceId; |
||||
|
||||
@ApiDocField(description = "ipPort") |
||||
private String ipPort; |
||||
|
||||
@ApiDocField(description = "ip") |
||||
private String ip; |
||||
|
||||
@ApiDocField(description = "port") |
||||
private int port; |
||||
|
||||
@ApiDocField(description = "status,服务状态,UP:已上线,OUT_OF_SERVICE:已下线") |
||||
private String status; |
||||
|
||||
@ApiDocField(description = "最后更新时间") |
||||
private String lastUpdatedTimestamp; |
||||
|
||||
@ApiDocField(description = "parentId") |
||||
private Integer parentId; |
||||
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss") |
||||
public Date getUpdateTime() { |
||||
if (StringUtils.isBlank(lastUpdatedTimestamp)) { |
||||
return null; |
||||
} |
||||
return new Date(Long.valueOf(lastUpdatedTimestamp)); |
||||
} |
||||
|
||||
public String getIpPort() { |
||||
return ip != null && port > 0 ? ip + ":" + port : ""; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,12 @@ |
||||
package com.gitee.sop.adminserver.config; |
||||
|
||||
import com.gitee.sop.registryapi.config.BaseRegistryConfig; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Configuration |
||||
public class RegistryConfig extends BaseRegistryConfig { |
||||
|
||||
} |
@ -1 +1 @@ |
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,c,a=t[0],i=t[1],f=t[2],l=0,h=[];l<a.length;l++)c=a[l],u[c]&&h.push(u[c][0]),u[c]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);s&&s(t);while(h.length)h.shift()();return o.push.apply(o,f||[]),n()}function n(){for(var e,t=0;t<o.length;t++){for(var n=o[t],r=!0,c=1;c<n.length;c++){var a=n[c];0!==u[a]&&(r=!1)}r&&(o.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-238a81e9":"5955f13d","chunk-25908fca":"3daff0c2","chunk-29e7142c":"994a3ac0","chunk-2d22c2e3":"46f37153","chunk-37401378":"4e39ec9b","chunk-4a59cbe4":"b5e74cc4","chunk-5f00e420":"5e409513","chunk-6a68a33e":"f59ae895","chunk-73b2dcec":"094bb2fa"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-238a81e9":1,"chunk-25908fca":1,"chunk-29e7142c":1,"chunk-37401378":1,"chunk-5f00e420":1,"chunk-6a68a33e":1,"chunk-73b2dcec":1};c[e]?t.push(c[e]):0!==c[e]&&n[e]&&t.push(c[e]=new Promise(function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-238a81e9":"e8e2beee","chunk-25908fca":"89ab33e8","chunk-29e7142c":"d10599db","chunk-2d22c2e3":"31d6cfe0","chunk-37401378":"a43114f3","chunk-4a59cbe4":"31d6cfe0","chunk-5f00e420":"aeebecd4","chunk-6a68a33e":"3b12267b","chunk-73b2dcec":"99cf6327"}[e]+".css",u=i.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var f=o[a],l=f.getAttribute("data-href")||f.getAttribute("href");if("stylesheet"===f.rel&&(l===r||l===u))return t()}var h=document.getElementsByTagName("style");for(a=0;a<h.length;a++){f=h[a],l=f.getAttribute("data-href");if(l===r||l===u)return t()}var s=document.createElement("link");s.rel="stylesheet",s.type="text/css",s.onload=t,s.onerror=function(t){var r=t&&t.target&&t.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],s.parentNode.removeChild(s),n(o)},s.href=u;var d=document.getElementsByTagName("head")[0];d.appendChild(s)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)t.push(r[2]);else{var o=new Promise(function(t,n){r=u[e]=[t,n]});t.push(r[2]=o);var f,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=a(e),f=function(t){l.onerror=l.onload=null,clearTimeout(h);var n=u[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,n[1](o)}u[e]=void 0}};var h=setTimeout(function(){f({type:"timeout",target:l})},12e4);l.onerror=l.onload=f,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var f=window["webpackJsonp"]=window["webpackJsonp"]||[],l=f.push.bind(f);f.push=t,f=f.slice();for(var h=0;h<f.length;h++)t(f[h]);var s=l;n()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.3cc1fa6b.js></script></body></html> |
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.4f0872ef.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function t(t){for(var r,c,o=t[0],i=t[1],f=t[2],l=0,d=[];l<o.length;l++)c=o[l],u[c]&&d.push(u[c][0]),u[c]=0;for(r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r]);h&&h(t);while(d.length)d.shift()();return a.push.apply(a,f||[]),n()}function n(){for(var e,t=0;t<a.length;t++){for(var n=a[t],r=!0,c=1;c<n.length;c++){var o=n[c];0!==u[o]&&(r=!1)}r&&(a.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},c={runtime:0},u={runtime:0},a=[];function o(e){return i.p+"static/js/"+({}[e]||e)+"."+{"chunk-009073d4":"28312808","chunk-238a81e9":"5955f13d","chunk-25908fca":"e7e4b6d5","chunk-29e7142c":"994a3ac0","chunk-2d2085ef":"a63a74dc","chunk-2d22c2e3":"4a098244","chunk-37401378":"4e39ec9b","chunk-4a59cbe4":"a6360c68","chunk-6a68a33e":"15951b55","chunk-73b2dcec":"094bb2fa"}[e]+".js"}function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.e=function(e){var t=[],n={"chunk-009073d4":1,"chunk-238a81e9":1,"chunk-25908fca":1,"chunk-29e7142c":1,"chunk-37401378":1,"chunk-6a68a33e":1,"chunk-73b2dcec":1};c[e]?t.push(c[e]):0!==c[e]&&n[e]&&t.push(c[e]=new Promise(function(t,n){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-009073d4":"0af16c7e","chunk-238a81e9":"e8e2beee","chunk-25908fca":"89ab33e8","chunk-29e7142c":"d10599db","chunk-2d2085ef":"31d6cfe0","chunk-2d22c2e3":"31d6cfe0","chunk-37401378":"a43114f3","chunk-4a59cbe4":"31d6cfe0","chunk-6a68a33e":"3b12267b","chunk-73b2dcec":"99cf6327"}[e]+".css",u=i.p+r,a=document.getElementsByTagName("link"),o=0;o<a.length;o++){var f=a[o],l=f.getAttribute("data-href")||f.getAttribute("href");if("stylesheet"===f.rel&&(l===r||l===u))return t()}var d=document.getElementsByTagName("style");for(o=0;o<d.length;o++){f=d[o],l=f.getAttribute("data-href");if(l===r||l===u)return t()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=t,h.onerror=function(t){var r=t&&t.target&&t.target.src||u,a=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");a.code="CSS_CHUNK_LOAD_FAILED",a.request=r,delete c[e],h.parentNode.removeChild(h),n(a)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)t.push(r[2]);else{var a=new Promise(function(t,n){r=u[e]=[t,n]});t.push(r[2]=a);var f,l=document.createElement("script");l.charset="utf-8",l.timeout=120,i.nc&&l.setAttribute("nonce",i.nc),l.src=o(e),f=function(t){l.onerror=l.onload=null,clearTimeout(d);var n=u[e];if(0!==n){if(n){var r=t&&("load"===t.type?"missing":t.type),c=t&&t.target&&t.target.src,a=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");a.type=r,a.request=c,n[1](a)}u[e]=void 0}};var d=setTimeout(function(){f({type:"timeout",target:l})},12e4);l.onerror=l.onload=f,document.head.appendChild(l)}return Promise.all(t)},i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i.oe=function(e){throw console.error(e),e};var f=window["webpackJsonp"]=window["webpackJsonp"]||[],l=f.push.bind(f);f.push=t,f=f.slice();for(var d=0;d<f.length;d++)t(f[d]);var h=l;n()})([]);</script><script src=static/js/chunk-elementUI.8ebdfbab.js></script><script src=static/js/chunk-libs.9cf9cc40.js></script><script src=static/js/app.095e8b9c.js></script></body></html> |
@ -1 +1 @@ |
||||
.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399}.limit-tip[data-v-0ec28e9a]{cursor:pointer;margin-left:10px} |
||||
.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399}.limit-tip[data-v-b81bfbde]{cursor:pointer;margin-left:10px} |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@ |
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22c2e3"],{f1ac:function(t,e,a){"use strict";a.r(e);var n=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"app-container"},[a("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchFormData,size:"mini"}},[a("el-form-item",{attrs:{label:"serviceId"}},[a("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"serviceId"},model:{value:t.searchFormData.serviceId,callback:function(e){t.$set(t.searchFormData,"serviceId",e)},expression:"searchFormData.serviceId"}})],1),t._v(" "),a("el-form-item",[a("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:t.onSearchTable}},[t._v("查询")])],1)],1),t._v(" "),a("el-table",{staticStyle:{width:"100%","margin-bottom":"20px"},attrs:{data:t.tableData,border:"","row-key":"id"}},[a("el-table-column",{attrs:{prop:"name",label:"服务名称(serviceId)",width:"200"}}),t._v(" "),a("el-table-column",{attrs:{prop:"instanceId",label:"instanceId",width:"250"}}),t._v(" "),a("el-table-column",{attrs:{prop:"ipAddr",label:"IP地址",width:"150"}}),t._v(" "),a("el-table-column",{attrs:{prop:"serverPort",label:"端口号",width:"100"}}),t._v(" "),a("el-table-column",{attrs:{prop:"status",label:"服务状态",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?a("el-tag",{attrs:{type:"success"}},[t._v("已上线")]):t._e(),t._v(" "),e.row.parentId>0&&"STARTING"===e.row.status?a("el-tag",{attrs:{type:"info"}},[t._v("正在启动")]):t._e(),t._v(" "),e.row.parentId>0&&"UNKNOWN"===e.row.status?a("el-tag",[t._v("未知")]):t._e(),t._v(" "),e.row.parentId>0&&("OUT_OF_SERVICE"===e.row.status||"DOWN"===e.row.status)?a("el-tag",{attrs:{type:"danger"}},[t._v("已下线")]):t._e()]}}])}),t._v(" "),a("el-table-column",{attrs:{prop:"updateTime",label:"最后更新时间",width:"160"}}),t._v(" "),a("el-table-column",{attrs:{label:"操作",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return t.onOffline(e.row)}}},[t._v("下线")]):t._e(),t._v(" "),e.row.parentId>0&&"OUT_OF_SERVICE"===e.row.status?a("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(a){return t.onOnline(e.row)}}},[t._v("上线")]):t._e()]}}])})],1)],1)},r=[],i=(a("7f7f"),a("ac6a"),{data:function(){return{searchFormData:{serviceId:""},tableData:[]}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("service.instance.list",this.searchFormData,function(t){this.tableData=this.buildTreeData(t.data)})},buildTreeData:function(t){return t.forEach(function(e){var a=e.parentId;0===a||t.forEach(function(t){if(t.id===a){var n=t.children;n||(n=[]),n.push(e),t.children=n}})}),t=t.filter(function(t){return 0===t.parentId}),t},onSearchTable:function(){this.loadTable()},onOffline:function(t){this.confirm("确定要下线【"+t.name+"】吗?",function(e){var a={serviceId:t.name,instanceId:t.instanceId};this.post("service.instance.offline",a,function(){this.tip("下线成功"),e()})})},onOnline:function(t){this.confirm("确定要上线【"+t.name+"】吗?",function(e){var a={serviceId:t.name,instanceId:t.instanceId};this.post("service.instance.online",a,function(){this.tip("上线成功"),e()})})}}}),s=i,o=a("2877"),l=Object(o["a"])(s,n,r,!1,null,null,null);e["default"]=l.exports}}]); |
@ -0,0 +1 @@ |
||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d22c2e3"],{f1ac:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"app-container"},[n("el-form",{staticClass:"demo-form-inline",attrs:{inline:!0,model:t.searchFormData,size:"mini"}},[n("el-form-item",{attrs:{label:"serviceId"}},[n("el-input",{staticStyle:{width:"250px"},attrs:{clearable:!0,placeholder:"serviceId"},model:{value:t.searchFormData.serviceId,callback:function(e){t.$set(t.searchFormData,"serviceId",e)},expression:"searchFormData.serviceId"}})],1),t._v(" "),n("el-form-item",[n("el-button",{attrs:{type:"primary",icon:"el-icon-search"},on:{click:t.onSearchTable}},[t._v("查询")])],1)],1),t._v(" "),n("el-table",{staticStyle:{width:"100%","margin-bottom":"20px"},attrs:{data:t.tableData,border:"","row-key":"id"}},[n("el-table-column",{attrs:{prop:"serviceId",label:"服务名称",width:"200"},scopedSlots:t._u([{key:"default",fn:function(e){return[n("span",{domProps:{innerHTML:t._s(t.renderServiceName(e.row))}})]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"ipPort",label:"IP端口",width:"250"}}),t._v(" "),n("el-table-column",{attrs:{prop:"status",label:"服务状态",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?n("el-tag",{attrs:{type:"success"}},[t._v("已上线")]):t._e(),t._v(" "),e.row.parentId>0&&"STARTING"===e.row.status?n("el-tag",{attrs:{type:"info"}},[t._v("正在启动")]):t._e(),t._v(" "),e.row.parentId>0&&"UNKNOWN"===e.row.status?n("el-tag",[t._v("未知")]):t._e(),t._v(" "),e.row.parentId>0&&("OUT_OF_SERVICE"===e.row.status||"DOWN"===e.row.status)?n("el-tag",{attrs:{type:"danger"}},[t._v("已下线")]):t._e()]}}])}),t._v(" "),n("el-table-column",{attrs:{prop:"updateTime",label:"最后更新时间",width:"160"}}),t._v(" "),n("el-table-column",{attrs:{label:"操作",width:"100"},scopedSlots:t._u([{key:"default",fn:function(e){return[e.row.parentId>0&&"UP"===e.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onOffline(e.row)}}},[t._v("下线")]):t._e(),t._v(" "),e.row.parentId>0&&"OUT_OF_SERVICE"===e.row.status?n("el-button",{attrs:{type:"text",size:"mini"},on:{click:function(n){return t.onOnline(e.row)}}},[t._v("上线")]):t._e()]}}])})],1)],1)},r=[],i=(n("ac6a"),{data:function(){return{searchFormData:{serviceId:""},tableData:[]}},created:function(){this.loadTable()},methods:{loadTable:function(){this.post("service.instance.list",this.searchFormData,function(t){this.tableData=this.buildTreeData(t.data)})},buildTreeData:function(t){return t.forEach(function(e){var n=e.parentId;0===n||t.forEach(function(t){if(t.id===n){var a=t.children;a||(a=[]),a.push(e),t.children=a}})}),t=t.filter(function(t){return 0===t.parentId}),t},onSearchTable:function(){this.loadTable()},onOffline:function(t){this.confirm("确定要下线【"+t.serviceId+"】吗?",function(e){this.post("service.instance.offline",t,function(){this.tip("下线成功"),e()})})},onOnline:function(t){this.confirm("确定要上线【"+t.serviceId+"】吗?",function(e){this.post("service.instance.online",t,function(){this.tip("上线成功"),e()})})},renderServiceName:function(t){var e="";if(t.children&&t.children.length>0){var n=t.children.filter(function(t){return"UP"===t.status}).length;e=" (".concat(n,"/").concat(t.children.length,")")}return t.serviceId+e}}}),o=i,s=n("2877"),l=Object(s["a"])(o,a,r,!1,null,null,null);e["default"]=l.exports}}]); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,179 @@ |
||||
<template> |
||||
<div class="app-container"> |
||||
<el-form :inline="true" :model="searchFormData" class="demo-form-inline" size="mini"> |
||||
<el-form-item label="角色码"> |
||||
<el-input v-model="searchFormData.roleCode" :clearable="true" placeholder="输入角色码" style="width: 250px;" /> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button type="primary" icon="el-icon-search" @click="loadTable">查询</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
<el-button type="primary" size="mini" icon="el-icon-plus" style="margin-bottom: 10px;" @click="onAdd">新增角色</el-button> |
||||
<el-table |
||||
:data="pageInfo.rows" |
||||
border |
||||
highlight-current-row |
||||
> |
||||
<el-table-column |
||||
prop="roleCode" |
||||
label="角色码" |
||||
width="200" |
||||
/> |
||||
<el-table-column |
||||
prop="description" |
||||
label="角色描述" |
||||
width="200" |
||||
/> |
||||
<el-table-column |
||||
prop="gmtCreate" |
||||
label="添加时间" |
||||
width="160" |
||||
/> |
||||
<el-table-column |
||||
prop="gmtModified" |
||||
label="修改时间" |
||||
width="160" |
||||
/> |
||||
<el-table-column |
||||
label="操作" |
||||
width="150" |
||||
> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" size="mini" @click="onTableUpdate(scope.row)">修改</el-button> |
||||
<el-button type="text" size="mini" @click="onTableDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<el-pagination |
||||
background |
||||
style="margin-top: 5px" |
||||
:current-page="searchFormData.pageIndex" |
||||
:page-size="searchFormData.pageSize" |
||||
:page-sizes="[5, 10, 20, 40]" |
||||
:total="pageInfo.total" |
||||
layout="total, sizes, prev, pager, next" |
||||
@size-change="onSizeChange" |
||||
@current-change="onPageIndexChange" |
||||
/> |
||||
<!--dialog--> |
||||
<el-dialog |
||||
:title="roleDialogTitle" |
||||
:visible.sync="roleDialogVisible" |
||||
:close-on-click-modal="false" |
||||
@close="resetForm('roleForm')" |
||||
> |
||||
<el-form |
||||
ref="roleForm" |
||||
:rules="roleDialogFormRules" |
||||
:model="roleDialogFormData" |
||||
label-width="120px" |
||||
size="mini" |
||||
> |
||||
<el-form-item prop="roleCode" label="角色码"> |
||||
<el-input v-show="roleDialogFormData.id === 0" v-model="roleDialogFormData.roleCode" /> |
||||
<span v-show="roleDialogFormData.id > 0">{{ roleDialogFormData.roleCode }}</span> |
||||
</el-form-item> |
||||
<el-form-item prop="description" label="角色描述"> |
||||
<el-input v-model="roleDialogFormData.description" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button @click="roleDialogVisible = false">取 消</el-button> |
||||
<el-button type="primary" @click="onRoleDialogSave">保 存</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
searchFormData: { |
||||
roleCode: '', |
||||
pageIndex: 1, |
||||
pageSize: 10 |
||||
}, |
||||
pageInfo: { |
||||
rows: [], |
||||
total: 0 |
||||
}, |
||||
roleDialogVisible: false, |
||||
roleDialogTitle: '', |
||||
roleDialogFormData: { |
||||
id: 0, |
||||
roleCode: '', |
||||
description: '' |
||||
}, |
||||
roleDialogFormRules: { |
||||
roleCode: [ |
||||
{ required: true, message: '不能为空', trigger: 'blur' }, |
||||
{ min: 1, max: 64, message: '长度在 1 到 100 个字符', trigger: 'blur' } |
||||
], |
||||
description: [ |
||||
{ max: 64, message: '不能超过 64 个字符', trigger: 'blur' } |
||||
] |
||||
}, |
||||
rulesIsvForm: { |
||||
appKey: [ |
||||
{ required: true, message: '不能为空', trigger: 'blur' }, |
||||
{ min: 1, max: 100, message: '长度在 1 到 100 个字符', trigger: 'blur' } |
||||
] |
||||
} |
||||
} |
||||
}, |
||||
created() { |
||||
this.loadTable() |
||||
}, |
||||
methods: { |
||||
loadTable: function() { |
||||
this.post('role.page', this.searchFormData, function(resp) { |
||||
this.pageInfo = resp.data |
||||
}) |
||||
}, |
||||
onTableUpdate: function(row) { |
||||
this.roleDialogTitle = '修改角色' |
||||
this.roleDialogVisible = true |
||||
this.$nextTick(() => { |
||||
Object.assign(this.roleDialogFormData, row) |
||||
}) |
||||
}, |
||||
onTableDelete: function(row) { |
||||
this.confirm(`确认要删除角色【${row.roleCode}】吗?`, function(done) { |
||||
const data = { |
||||
id: row.id |
||||
} |
||||
this.post('role.del', data, function() { |
||||
done() |
||||
this.tip('删除成功') |
||||
this.loadTable() |
||||
}) |
||||
}) |
||||
}, |
||||
onRoleDialogSave: function() { |
||||
this.$refs.roleForm.validate((valid) => { |
||||
if (valid) { |
||||
const uri = this.roleDialogFormData.id ? 'role.update' : 'role.add' |
||||
this.post(uri, this.roleDialogFormData, function() { |
||||
this.roleDialogVisible = false |
||||
this.loadTable() |
||||
}) |
||||
} |
||||
}) |
||||
}, |
||||
onSizeChange: function(size) { |
||||
this.searchFormData.pageSize = size |
||||
this.loadTable() |
||||
}, |
||||
onAdd: function() { |
||||
this.roleDialogTitle = '新增角色' |
||||
this.roleDialogVisible = true |
||||
this.roleDialogFormData.id = 0 |
||||
}, |
||||
onPageIndexChange: function(pageIndex) { |
||||
this.searchFormData.pageIndex = pageIndex |
||||
this.loadTable() |
||||
} |
||||
} |
||||
} |
||||
</script> |
@ -1,8 +1,11 @@ |
||||
# sop-common |
||||
|
||||
- sop-gateway-common:提供给网关使用 |
||||
- sop-registry-api:注册中心API |
||||
- sop-service-common:提供给微服务端使用,需要打成jar |
||||
|
||||
正式开发请将这些模块上传的maven私服 |
||||
|
||||
- 打包成jar:`mvn clean package` |
||||
- 上传到本机仓库:`mvn clean install` |
||||
- 上传到maven私服:`mvn clean deploy` |
@ -1,3 +1,3 @@ |
||||
# sop-gateway-common |
||||
|
||||
zuul通用组件,主要封装网关的一些功能。 |
||||
网关通用组件,主要封装网关的一些功能。 |
||||
|
@ -0,0 +1,74 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
<groupId>com.gitee.sop</groupId> |
||||
<artifactId>sop-registry-api</artifactId> |
||||
<version>1.12.0-SNAPSHOT</version> |
||||
|
||||
<properties> |
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
||||
<java.version>1.8</java.version> |
||||
<okhttp.version>3.11.0</okhttp.version> |
||||
</properties> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>com.squareup.okhttp3</groupId> |
||||
<artifactId>okhttp</artifactId> |
||||
<version>${okhttp.version}</version> |
||||
</dependency> |
||||
|
||||
<!-- nacos sdk --> |
||||
<dependency> |
||||
<groupId>com.alibaba.nacos</groupId> |
||||
<artifactId>nacos-client</artifactId> |
||||
<version>1.0.1</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>org.springframework</groupId> |
||||
<artifactId>spring-context</artifactId> |
||||
<version>5.1.6.RELEASE</version> |
||||
<optional>true</optional> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.projectlombok</groupId> |
||||
<artifactId>lombok</artifactId> |
||||
<version>1.18.6</version> |
||||
<optional>true</optional> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-autoconfigure</artifactId> |
||||
<version>2.1.4.RELEASE</version> |
||||
<optional>true</optional> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>junit</groupId> |
||||
<artifactId>junit</artifactId> |
||||
<version>4.11</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
|
||||
</dependencies> |
||||
|
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.apache.maven.plugins</groupId> |
||||
<artifactId>maven-compiler-plugin</artifactId> |
||||
<version>3.1</version> |
||||
<configuration> |
||||
<source>${java.version}</source> |
||||
<target>${java.version}</target> |
||||
<encoding>UTF-8</encoding> |
||||
</configuration> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
|
||||
</project> |
@ -0,0 +1,3 @@ |
||||
# sop-registry-api |
||||
|
||||
统一各注册中心接口 |
@ -1,4 +1,4 @@ |
||||
package com.gitee.sop.adminserver.bean; |
||||
package com.gitee.sop.registryapi.bean; |
||||
|
||||
import lombok.Data; |
||||
|
@ -1,4 +1,4 @@ |
||||
package com.gitee.sop.adminserver.bean; |
||||
package com.gitee.sop.registryapi.bean; |
||||
|
||||
import lombok.Data; |
||||
|
@ -1,4 +1,4 @@ |
||||
package com.gitee.sop.adminserver.bean; |
||||
package com.gitee.sop.registryapi.bean; |
||||
|
||||
import lombok.Data; |
||||
|
@ -1,4 +1,4 @@ |
||||
package com.gitee.sop.adminserver.bean; |
||||
package com.gitee.sop.registryapi.bean; |
||||
|
||||
import lombok.Data; |
||||
import org.springframework.util.CollectionUtils; |
@ -0,0 +1,24 @@ |
||||
package com.gitee.sop.registryapi.bean; |
||||
|
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Getter |
||||
@Setter |
||||
public class ServiceInfo { |
||||
/** 服务名称 */ |
||||
private String serviceId; |
||||
/** 实例列表 */ |
||||
private List<ServiceInstance> instances = Collections.emptyList(); |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "服务名称: " + serviceId + ", 实例数:" + instances.size(); |
||||
} |
||||
} |
@ -0,0 +1,32 @@ |
||||
package com.gitee.sop.registryapi.bean; |
||||
|
||||
import lombok.Data; |
||||
|
||||
@Data |
||||
public class ServiceInstance { |
||||
/** |
||||
* 实例id |
||||
*/ |
||||
private String instanceId; |
||||
|
||||
/** |
||||
* 服务名称 |
||||
*/ |
||||
private String serviceId; |
||||
|
||||
/** |
||||
* ip |
||||
*/ |
||||
private String ip; |
||||
|
||||
/** |
||||
* port |
||||
*/ |
||||
private int port; |
||||
|
||||
/** |
||||
* 服务状态,UP:已上线,OUT_OF_SERVICE:已下线 |
||||
*/ |
||||
private String status; |
||||
|
||||
} |
@ -0,0 +1,36 @@ |
||||
package com.gitee.sop.registryapi.config; |
||||
|
||||
import com.gitee.sop.registryapi.service.RegistryService; |
||||
import com.gitee.sop.registryapi.service.impl.RegistryServiceEureka; |
||||
import com.gitee.sop.registryapi.service.impl.RegistryServiceNacos; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.context.annotation.Bean; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public class BaseRegistryConfig { |
||||
|
||||
/** |
||||
* 当配置了registry.name=eureka生效 |
||||
* |
||||
* @return |
||||
*/ |
||||
@Bean |
||||
@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "eureka") |
||||
RegistryService registryServiceEureka() { |
||||
return new RegistryServiceEureka(); |
||||
} |
||||
|
||||
/** |
||||
* 当配置了registry.name=nacos生效 |
||||
* |
||||
* @return |
||||
*/ |
||||
@Bean |
||||
@ConditionalOnProperty(prefix = "registry", name = "name", havingValue = "nacos") |
||||
RegistryService registryServiceNacos() { |
||||
return new RegistryServiceNacos(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,36 @@ |
||||
package com.gitee.sop.registryapi.service; |
||||
|
||||
import com.gitee.sop.registryapi.bean.ServiceInfo; |
||||
import com.gitee.sop.registryapi.bean.ServiceInstance; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
public interface RegistryService { |
||||
/** |
||||
* 获取所有服务列表 |
||||
* |
||||
* @param pageNo 当前页码 |
||||
* @param pageSize 分页大小 |
||||
* @return 返回服务列表 |
||||
*/ |
||||
List<ServiceInfo> listAllService(int pageNo, int pageSize) throws Exception; |
||||
|
||||
/** |
||||
* 服务上线 |
||||
* |
||||
* @param serviceInstance |
||||
*/ |
||||
void onlineInstance(ServiceInstance serviceInstance) throws Exception; |
||||
|
||||
/** |
||||
* 服务下线 |
||||
* |
||||
* @param serviceInstance |
||||
*/ |
||||
void offlineInstance(ServiceInstance serviceInstance) throws Exception; |
||||
|
||||
|
||||
} |
@ -0,0 +1,90 @@ |
||||
package com.gitee.sop.registryapi.service.impl; |
||||
|
||||
import com.alibaba.fastjson.JSON; |
||||
import com.gitee.sop.registryapi.bean.EurekaApplication; |
||||
import com.gitee.sop.registryapi.bean.EurekaApps; |
||||
import com.gitee.sop.registryapi.bean.EurekaInstance; |
||||
import com.gitee.sop.registryapi.bean.EurekaUri; |
||||
import com.gitee.sop.registryapi.bean.ServiceInfo; |
||||
import com.gitee.sop.registryapi.bean.ServiceInstance; |
||||
import com.gitee.sop.registryapi.service.RegistryService; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import okhttp3.OkHttpClient; |
||||
import okhttp3.Request; |
||||
import okhttp3.Response; |
||||
import org.apache.commons.lang3.StringUtils; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.util.CollectionUtils; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* eureka接口实现 |
||||
* @author tanghc |
||||
*/ |
||||
@Slf4j |
||||
public class RegistryServiceEureka implements RegistryService { |
||||
|
||||
OkHttpClient client = new OkHttpClient(); |
||||
|
||||
@Value("${registry.eureka-server-addr:}") |
||||
private String eurekaUrl; |
||||
|
||||
@Override |
||||
public List<ServiceInfo> listAllService(int pageNo, int pageSize) throws Exception { |
||||
if (StringUtils.isBlank(eurekaUrl)) { |
||||
return Collections.emptyList(); |
||||
} |
||||
String json = this.requestEurekaServer(EurekaUri.QUERY_APPS); |
||||
EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class); |
||||
|
||||
List<ServiceInfo> serviceInfoList = new ArrayList<>(); |
||||
List<EurekaApplication> applicationList = eurekaApps.getApplications().getApplication(); |
||||
for (EurekaApplication eurekaApplication : applicationList) { |
||||
ServiceInfo serviceInfo = new ServiceInfo(); |
||||
serviceInfo.setServiceId(eurekaApplication.getName()); |
||||
List<EurekaInstance> instanceList = eurekaApplication.getInstance(); |
||||
if (!CollectionUtils.isEmpty(instanceList)) { |
||||
serviceInfo.setInstances(new ArrayList<>(instanceList.size())); |
||||
for (EurekaInstance eurekaInstance : instanceList) { |
||||
ServiceInstance serviceInstance = new ServiceInstance(); |
||||
serviceInstance.setInstanceId(eurekaInstance.getInstanceId()); |
||||
serviceInstance.setServiceId(serviceInfo.getServiceId()); |
||||
serviceInstance.setIp(eurekaInstance.getIpAddr()); |
||||
serviceInstance.setPort(Integer.valueOf(eurekaInstance.fetchPort())); |
||||
serviceInstance.setStatus(eurekaInstance.getStatus()); |
||||
serviceInfo.getInstances().add(serviceInstance); |
||||
} |
||||
} |
||||
serviceInfoList.add(serviceInfo); |
||||
} |
||||
return serviceInfoList; |
||||
} |
||||
|
||||
|
||||
|
||||
@Override |
||||
public void onlineInstance(ServiceInstance serviceInstance) throws Exception { |
||||
this.requestEurekaServer(EurekaUri.ONLINE_SERVICE, serviceInstance.getServiceId(), serviceInstance.getInstanceId()); |
||||
} |
||||
|
||||
@Override |
||||
public void offlineInstance(ServiceInstance serviceInstance) throws Exception { |
||||
this.requestEurekaServer(EurekaUri.OFFLINE_SERVICE, serviceInstance.getServiceId(), serviceInstance.getInstanceId()); |
||||
} |
||||
|
||||
private String requestEurekaServer(EurekaUri eurekaUri, String... args) throws IOException { |
||||
Request request = eurekaUri.getRequest(this.eurekaUrl, args); |
||||
Response response = client.newCall(request).execute(); |
||||
if (response.isSuccessful()) { |
||||
return response.body().string(); |
||||
} else { |
||||
log.error("操作失败,url:{}, msg:{}, code:{}", eurekaUri.getUri(args), response.message(), response.code()); |
||||
throw new RuntimeException("操作失败"); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,106 @@ |
||||
package com.gitee.sop.registryapi.service.impl; |
||||
|
||||
import com.alibaba.nacos.api.exception.NacosException; |
||||
import com.alibaba.nacos.api.naming.NamingFactory; |
||||
import com.alibaba.nacos.api.naming.NamingService; |
||||
import com.alibaba.nacos.api.naming.pojo.Instance; |
||||
import com.alibaba.nacos.api.naming.pojo.ListView; |
||||
import com.gitee.sop.registryapi.bean.ServiceInfo; |
||||
import com.gitee.sop.registryapi.bean.ServiceInstance; |
||||
import com.gitee.sop.registryapi.service.RegistryService; |
||||
import okhttp3.FormBody; |
||||
import okhttp3.OkHttpClient; |
||||
import okhttp3.Request; |
||||
import okhttp3.Response; |
||||
import org.apache.commons.lang3.StringUtils; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.util.CollectionUtils; |
||||
|
||||
import javax.annotation.PostConstruct; |
||||
import java.io.IOException; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* nacos接口实现 |
||||
* @author tanghc |
||||
*/ |
||||
public class RegistryServiceNacos implements RegistryService { |
||||
|
||||
OkHttpClient client = new OkHttpClient(); |
||||
|
||||
@Value("${registry.nacos-server-addr:}") |
||||
private String nacosAddr; |
||||
|
||||
private NamingService namingService; |
||||
|
||||
@PostConstruct |
||||
public void after() throws NacosException { |
||||
if (StringUtils.isNotBlank(nacosAddr)) { |
||||
namingService = NamingFactory.createNamingService(nacosAddr); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public List<ServiceInfo> listAllService(int pageNo, int pageSize) throws Exception { |
||||
ListView<String> servicesOfServer = namingService.getServicesOfServer(pageNo, pageSize); |
||||
List<String> serverList = servicesOfServer.getData(); |
||||
List<ServiceInfo> serviceInfoList = new ArrayList<>(); |
||||
for (String serviceName : serverList) { |
||||
ServiceInfo serviceInfo = new ServiceInfo(); |
||||
serviceInfo.setServiceId(serviceName); |
||||
List<Instance> instanceList = namingService.getAllInstances(serviceName); |
||||
if (!CollectionUtils.isEmpty(instanceList)) { |
||||
serviceInfo.setInstances(new ArrayList<>(instanceList.size())); |
||||
for (Instance instance : instanceList) { |
||||
ServiceInstance serviceInstance = new ServiceInstance(); |
||||
serviceInstance.setInstanceId(instance.getInstanceId()); |
||||
serviceInstance.setServiceId(serviceInfo.getServiceId()); |
||||
serviceInstance.setIp(instance.getIp()); |
||||
serviceInstance.setPort(instance.getPort()); |
||||
boolean isOnline = instance.getWeight() > 0; |
||||
String status = isOnline ? "UP" : "OUT_OF_SERVICE"; |
||||
serviceInstance.setStatus(status); |
||||
serviceInfo.getInstances().add(serviceInstance); |
||||
} |
||||
} |
||||
serviceInfoList.add(serviceInfo); |
||||
} |
||||
return serviceInfoList; |
||||
} |
||||
|
||||
@Override |
||||
public void onlineInstance(ServiceInstance serviceInstance) throws Exception { |
||||
Map<String, String> params = new HashMap<>(); |
||||
// 上线,把权重设置成1
|
||||
params.put("weight", "1"); |
||||
this.updateInstance(serviceInstance, params); |
||||
} |
||||
|
||||
@Override |
||||
public void offlineInstance(ServiceInstance serviceInstance) throws Exception { |
||||
Map<String, String> params = new HashMap<>(); |
||||
// 下线,把权重设置成0
|
||||
params.put("weight", "0"); |
||||
this.updateInstance(serviceInstance, params); |
||||
} |
||||
|
||||
private Response updateInstance(ServiceInstance serviceInstance, Map<String, String> params) throws IOException { |
||||
FormBody.Builder builder = new FormBody.Builder(); |
||||
for (Map.Entry<String, String> entry : params.entrySet()) { |
||||
builder.add(entry.getKey(), String.valueOf(entry.getValue())); |
||||
} |
||||
builder.add("serviceName", serviceInstance.getServiceId()) |
||||
.add("ip", serviceInstance.getIp()) |
||||
.add("port", String.valueOf(serviceInstance.getPort())); |
||||
FormBody formBody = builder.build(); |
||||
final Request request = new Request.Builder() |
||||
.url("http://" + nacosAddr + "/nacos/v1/ns/instance") |
||||
.put(formBody) |
||||
.build(); |
||||
|
||||
return client.newCall(request).execute(); |
||||
} |
||||
} |
@ -0,0 +1,64 @@ |
||||
package com.gitee.sop; |
||||
|
||||
import com.alibaba.fastjson.JSON; |
||||
import com.gitee.sop.alipay.AlipayApiException; |
||||
import com.gitee.sop.alipay.AlipaySignature; |
||||
import org.junit.Test; |
||||
|
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
|
||||
public class LoadBalanceTest extends TestBase { |
||||
|
||||
String url = "http://localhost:8081/api"; // zuul
|
||||
String appId = "2019032617262200001"; |
||||
// 支付宝私钥
|
||||
String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ="; |
||||
|
||||
// 测试稳定性
|
||||
@Test |
||||
public void testLoadBalance() throws Exception { |
||||
int i = 0; |
||||
while (i++ < 50) { |
||||
doTest(); |
||||
Thread.sleep(3000); |
||||
} |
||||
} |
||||
|
||||
private void doTest() throws AlipayApiException { |
||||
// 公共请求参数
|
||||
Map<String, String> params = new HashMap<String, String>(); |
||||
params.put("app_id", appId); |
||||
params.put("method", "alipay.story.get"); |
||||
params.put("format", "json"); |
||||
params.put("charset", "utf-8"); |
||||
params.put("sign_type", "RSA2"); |
||||
params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); |
||||
params.put("version", "1.0"); |
||||
|
||||
// 业务参数
|
||||
Map<String, String> bizContent = new HashMap<>(); |
||||
bizContent.put("id", "1"); |
||||
bizContent.put("name", "葫芦娃"); |
||||
|
||||
params.put("biz_content", JSON.toJSONString(bizContent)); |
||||
|
||||
// System.out.println("----------- 请求信息 -----------");
|
||||
// System.out.println("请求参数:" + buildParamQuery(params));
|
||||
// System.out.println("商户秘钥:" + privateKey);
|
||||
String content = AlipaySignature.getSignContent(params); |
||||
// System.out.println("待签名内容:" + content);
|
||||
String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8"); |
||||
// System.out.println("签名(sign):" + sign);
|
||||
|
||||
params.put("sign", sign); |
||||
|
||||
// System.out.println("----------- 返回结果 -----------");
|
||||
String responseData = get(url, params);// 发送请求
|
||||
System.out.println(responseData); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,12 @@ |
||||
package com.gitee.sop.websiteserver.config; |
||||
|
||||
import com.gitee.sop.registryapi.config.BaseRegistryConfig; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* @author tanghc |
||||
*/ |
||||
@Configuration |
||||
public class RegistryConfig extends BaseRegistryConfig { |
||||
|
||||
} |
Loading…
Reference in new issue