网站首页 > 博客文章 正文
- 服务发现数据模型
- 服务管理
- Nacos四个特性
- Nacos之Raft算法
- Nacos实战与综合架构演示
服务发现数据模型
Nacos是阿里内部经过多年生产实践后提炼出的数据模型,这种模型是一种服务-集群-实例的三层模型,这样基本可以满足服务在所有场景下的数据存储和管理。
命名空间(Namespace)
用于进行租户粒度的配置隔离,命名空间不仅适用于nacos的配置管理,同样适用于服务发现。Namespace 的常 用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
服务及服务名
提供给客户端的软件功能,通过预定义接口网络访问并可以独立部署的系统称之为服务。服务提供的标识,通过该标识可以唯一确定其指代的服务,称之为服务名,消费方通过指定服务名实现服务间的调用。
实例
提供一个或多个服务的具有可访问网络地址(IP:Port)的进程,启动一个服务,就产生了一个服务实例。
元信息
Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标 签 (label),从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。
集群
服务实例的集合,服务实例组成一个默认集群, 集群可以被进一步按需求划分,划分的单位可以是虚拟集群,相同 集群下的实例才能相互感知。
应用通过Namespace、Service、Cluster(DEFAULT)的配置,描述了该服务向哪个环境(如开发环境)的哪个集群 注册实例。
spring:
application:
name: transaction‐service #服务(名)Service
cloud:
nacos:
discovery:
server‐addr: 127.0.0.1:7283 # 注册中心地址
namespace: a1f8e863‐3117‐48c4‐9dd3‐e9ddc2af90a8 # 开发环境
cluster‐name: DEFAULT # 默认集群,可不填写
- Note: 集群作为实例的隔离,相同集群的实例才能相互感知。
- Note: namespace、cluster-name若不填写都将采取默认值,namespace的默认是public命名空间, cluster-name的默认值为DEFAULT集群。
服务管理
开发者或者运维人员往往需要在服务注册后,通过友好的界面来查看服务的注册情况,包括当前系统注册的所有服务和每个服务的详情。并在有权限控制的情况下,进行服务的一些配置的编辑操作。Nacos在目前最新版本开放的控制台的服务发现部分,主要就是提供用户一个基本的运维页面,能够查看、编辑当前注册的服务,这些功能集中 在Nacos控制台的服务管理一级菜单内。
服务列表管理
服务列表帮助用户以统一的视图管理其所有的微服务以及服务健康状态。整体界面布局是左上角有服务的搜索框和 搜索按钮,页面中央是服务列表的展示。服务列表主要展示服务名、集群数目、实例数目、健康实例数目和详情按钮五个栏目。
在服务列表页面点击详情,可以看到服务的详情。可以查看服务、集群和实例的基本信息。
服务流量权重支持及流量保护
Nacos 为用户提供了流量权重控制的能力,同时开放了服务流量的阈值保护,以帮助用户更好的保护服务服务提 供者集群不被意外打垮。如下图所以,可以点击实例的编辑按钮,修改实例的权重。如果想增加实例的流量,可以 将权重调大,如果不想实例接收流量,则可以将权重设为0。
服务元数据管理
Nacos提供多个维度的服务元数据的暴露,帮助用户存储自定义的信息。这些信息都是以K-V的数据结构存储,在 控制台上,会以k1=v1,k2=v2这样的格式展示。类似的,编辑元数据可以通过相同的格式进行。例如服务的元数据 编辑,首先点击服务详情页右上角的“编辑服务”按钮,然后在元数据输入框输入:version=1.0。
点击确认,就可以在服务详情页面,看到服务的元数据已经更新了。
服务优雅上下线
Nacos还提供服务实例的上下线操作,在服务详情页面,可以点击实例的“上线”或者“下线”按钮,被下线的实例, 将不会包含在健康的实例列表里。
上下线测试:
(1)分别启动快速上手中的quickstart-consumer与quickstart-provider工程,更改quickstart-provide中的启动 端口,再次启动quickstart-provider,让quickstart-provider服务拥有两个实例。
(2)多次访问http://127.0.0.1:56020/service ,让consumer调用provider时触发负载均衡。 (3)观察provider的2个实例控制台,可发现实例调用被均匀负载。 (4)在provider的服务详情页面,让某实例下线。
(5)多次访问http://127.0.0.1:56020/service ,观察控制台,发现下线的实例已不再接收流量。 ( 6)在provider的服务详情页面,让该实例恢复上线状态。 (7)多次访问http://127.0.0.1:56020/service ,观察控制台,发现恢复上线的实例已恢复流量访问。
Nacos四个特性
动态配置服务
动态配置服务允许您在所有环境中以集中和动态的方式管理所有服务的配置。Nacos消除了在更新配置时重新部署应用程序和服务的需要,这使配置更改更加高效和灵活。
服务发现与服务健康监测
Nacos使服务更容易注册自己并通过DNS或HTTP接口发现其他服务。Nacos还提供服务的实时健康检查,以防止向不健康的主机或服务实例发送请求。
服务和元数据管理
Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略、服务的 SLA 以及最首要的 metrics 统计数据。
动态DNS服务
Nacos支持加权路由,使您可以更轻松地在数据中心的生产环境中实施中间层负载平衡,灵活的路由策略,流量控制和简单的DNS解析服务。它可以帮助您轻松实现基于DNS的服务发现,并防止应用程序耦合到特定于供应商的服务发现API。
Nacos之Raft算法
由于篇幅过长原因,这里不对Raft算法进行详细介绍,感兴趣的看官老爷可以持续关注后续文章
Nacos实战与综合架构演示
本章内容将指引大家使用Nacos集成一个微服务的基础架构,并讨论其合理性。
总体结构
系统架构图如下:
组件说明:
API网关 :系统统一入口,屏蔽架构内部结构,统一安全拦截,采用Zuul实现。 application-1 :应用1,模拟应用,提供http接口服务。 service-1 :微服务1,模拟微服务,提供dubbo接口服务。 service-2 :微服务2,模拟微服务,提供dubbo接口服务。
调用流程:
所有访问系统的请求都要经过网关,网关转发Http请求至application-1,application-1使用dubbo调用service1完 成自身业务,而后sevice1调用service2完成自身业务。至此,完成所有组件贯穿。
架构中application与sevice的区别是什么
- service提供了基础服务功能;application组装基础服务功能,提供给用户直接可用的业务。
- service服务粒度小、功能基础,不易发生改变;application提供上游业务功能,紧贴业务需求,容易发生改变。
- 形成service支撑application的整体架构,增加多变的application甚至不需要变动service
工程结构说明
采用maven工程,结构如下:
nacos‐micro‐service 整体父工程
├─api‐gateway API网关,端口:56010
├─application‐1 应用1,端口:56020
├─service‐1 服务1父工程
│ ├─service‐1‐api 服务1API
│ └─service‐1‐server 服务1实现,端口:56030
└─service‐2 服务2父工程
├─service‐2‐api 服务2API
└─service‐2‐server 服务2实现,端口:56040
创建父工程
创建 artifactId 名为 nacos-micro-service 的 Maven 工程,此父工程继承nacos-discovery父工程,间接指定 了Spring boot、spring cloud 以及spring-cloud-alibaba的依赖版本。
nacos-discovery的pom.xml如下:
<groupId>com.htym.nacos</groupId>
<artifactId>nacos-micro-service</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>application-1</module>
</modules>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF‐8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF‐8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring‐cloud‐alibaba‐dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐dependencies</artifactId>
<version>Greenwich.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐dependencies</artifactId>
<version>2.1.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
实现application1
application1属于应用层,提供http接口服务。
(1)初始化 application-1 Maven 工程
<parent>
<artifactId>nacos-micro-service</artifactId>
<groupId>com.htym.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>application-1</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring‐cloud‐starter‐alibaba‐nacos‐config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring‐cloud‐starter‐alibaba‐nacos‐discovery</artifactId>
</dependency>
</dependencies>
(2)实现 application-1 功能
package com.htym.nacos.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Application1Controller {
@GetMapping("/service")
public String service(){
return "test";
}
}
(3) application1 配置
定义bootstrap.yml
server:
port: 56020
servlet:
context-path: /application1
spring:
application:
name: application1
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
#namespace: 默认public
#cluster-name: 默认default
config:
server-addr: 127.0.0.1:8848
namespace: 0b56546c-23a4-4e55-835a-06472ef318c9
group: DEFAULT_GROUP
refresh-enabled: true
file-extension: yaml
(4) application1 启动
package com.htym.nacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Application1Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Application1Bootstrap.class,args);
}
}
当 Application1Bootstrap 启动后,应用 application1 将出现在 Nacos 控制台界面。
实现 Service1
定义父工程
定义service1父工程,pom.xml如下:
<parent>
<artifactId>nacos-micro-service</artifactId>
<groupId>com.htym.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service1</artifactId>
<packaging>pom</packaging>
定义service-1-api
为了方便其它服务调用dubbo服务,专门定义api工程,此工程将作为jar被其它工程依赖。
定义service-1-api工程,pom.xml如下:
<parent>
<artifactId>service1</artifactId>
<groupId>com.htym.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service1-api</artifactId>
定义服务接口:
package com.htym.nacos.service;
public interface ConsummerService {
public String service();
}
实现service-1-server
(1)初始化 service-1-server Maven 工程
与服务提供方 Maven工程类似,需添加相关 Maven 依赖:
<parent>
<artifactId>service1</artifactId>
<groupId>com.htym.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service1-server</artifactId>
<dependencies>
<dependency>
<groupId>com.htym.nacos</groupId>
<artifactId>service1-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
<version>2021.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
(2)实现 Dubbo 服务
package com.htym.nacos.service;
import org.apache.dubbo.config.annotation.DubboService;
@DubboService
public class ConsummerServiceImpl implements ConsummerService{
@Override
public String service() {
return "consummer invoker";
}
}
(3)配置 Dubbo 服务
Service2 作为Dubbo服务消费方配置与服务提供方类似,注意,service1不仅是消费方,同时还是服务提供方:
server:
port: ${port:56030}
spring:
application:
name: service1
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
namespace: 0b56546c-23a4-4e55-835a-06472ef318c9
server-addr: 127.0.0.1:8848
file-extension: yaml
group: DEFAULT_GROUP
dubbo:
scan:
base-packages: com.htym.nacos
protocol:
name: dubbo
port: ${port:20881}
registry:
address: nacos://127.0.0.1:8848
application:
qos-enable: false
consumer:
check: false
以上 YAML 内容,dubbo开头的为dubbo服务 的配置:
- dubbo.scan.base-packages : 指定 Dubbo 服务实现类的扫描基准包,将 org.apache.dubbo.config.annotation.DubboService注解标注的service暴露为dubbo服务。
- dubbo.protocol : Dubbo 服务暴露的协议配置,其中子属性 name 为协议名称, port 为dubbo协议端口 可以指定多协议,如:dubbo.protocol.rmi.port=1099
- dubbo.registry : Dubbo 服务注册中心配置,其中子属性 address 的值 "nacos://127.0.0.1:8848",说明 dubbo服务注册到nacos 相当于原生dubbo的xml配置中的
上半部分为SpringCloud的相关配置:
- spring.application.name : Spring 应用名称,用于 Spring Cloud 服务注册和发现。 该值在 Dubbo Spring Cloud 加持下被视作 dubbo.application.name ,因此,无需再显示地配置 dubbo.application.name
- spring.cloud.nacos.discovery : Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器 主机和端口
- spring.cloud.nacos.config : Nacos 配置中心配置,其中子属性 server-addr 指定 Nacos 服务器主机和端 口。
(4)启动服务消费方应用
package com.htym.nacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class Service1Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Service1Bootstrap.class,args);
}
}
当 Service1Bootstrap 启动后,应用 service1 将出现在 Nacos 控制台界面。
启动成功,观察nacos服务列表
实现 application1调用Service1
现在service1已暴露dubbo服务并注册到nacos中,下边实现application1调用service1
引用service1
下边在application1中引用service1 在pom.xml中引入service-1-api的依赖
<dependency>
<groupId>com.itheima.nacos</groupId>
<artifactId>service‐1‐api</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency>
引入 spring-cloud-starter-dubbo依赖,它会根据接口生成代理对象
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring‐cloud‐starter‐dubbo</artifactId>
</dependency>
实现远程调用
@RestController
public class Application1Controller {
@DubboReference
private ConsumerService consumerService;
@GetMapping("/service")
public String service(){
return "test" + consumerService.service();
}
}
测试:
请求:http://localhost:56020/application1/service. consumerService正常生成代理对象,service1被调用。
实现 Service2
如上面设计所示,Service2需要暴露dubbo接口以供service1消费,若想在Spring cloud Alibaba中集成并使用 dubbo。
定义父工程
定义service2父工程,pom.xml如下:
<parent>
<artifactId>nacos‐micro‐service</artifactId>
<groupId>com.itheima.nacos</groupId>
<version>1.0‐SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Service2</artifactId>
定义service-2-api
定义service-2-api工程,pom.xml如下:
<parent>
<artifactId>Service2</artifactId>
<groupId>com.itheima.nacos</groupId>
<version>1.0‐SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service‐2‐api</artifactId>
并定义服务接口,Dubbo 服务接口是服务提供方与消费方的远程通讯契约,通常由普通的 Java 接口(interface) 来声明,如 ProviderService 接口:
package com.itheima.microservice.service2.api;
public interface ProviderService {
String service();
}
实现service-2-server
(1)初始化 service-2-server Maven 工程
首先,创建 artifactId 名为 service-2-server 的 Maven 工程,并在其 pom.xml 文件中增添 Dubbo Spring Cloud 必要的依赖:
<parent>
<artifactId>service1</artifactId>
<groupId>com.htym.nacos</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service1-server</artifactId>
<dependencies>
<dependency>
<groupId>com.htym.nacos</groupId>
<artifactId>service2-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
<version>2021.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
以上依赖 artifact 说明如下:
- service-2-api : 提供 ProviderService 接口的 artifact
- spring-boot-starter-web : Spring Boot starter artifact ,间接引入 spring-boot artifact
- spring-cloud-starter-dubbo : Dubbo Spring Cloud Starter artifact ,间接引入 dubbo-spring-bootstarter 等 artifact
- spring-cloud-starter-alibaba-nacos-discovery : Nacos Spring Cloud 服务注册与发现 artifact
(2)实现 Dubbo 服务
ProviderService 作为暴露的 Dubbo 服务接口,服务提供方 service-2-server 需要将其实现:
package com.itheima.microservice.service2.service;
@org.apache.dubbo.config.annotation.Service
public class ProviderServiceImpl implements ProviderService {
@Override
public String service() {
return "Provider invoke";
}
}
其中, @org.apache.dubbo.config.annotation.Service 是 Dubbo 服务注解,仅声明该 Java 服务(本地)实现 为 Dubbo 服务。 因此,下一步需要将其配置 Dubbo 服务(远程)。
(3)配置 Dubbo 服务
在暴露 Dubbo 服务方面,推荐开发人员外部化配置的方式,即指定 Java 服务实现类的扫描基准包。
server:
port: ${port:56030}
spring:
application:
name: service1
main:
allow-bean-definition-overriding: true
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
namespace: 0b56546c-23a4-4e55-835a-06472ef318c9
server-addr: 127.0.0.1:8848
file-extension: yaml
group: DEFAULT_GROUP
dubbo:
scan:
base-packages: com.htym.nacos
protocol:
name: dubbo
port: ${port:20881}
registry:
address: nacos://127.0.0.1:8848
application:
qos-enable: false
consumer:
check: false
(4)启动服务提供方应用
Dubbo Spring Cloud 引导类与普通 Spring Cloud 应用并无差别,如下所示:
@SpringBootApplication
@EnableDiscoveryClient
public class Service2Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Service2Bootstrap.class, args);
}
}
在引导 Service2Bootstrap 之前,请提前启动 Nacos 服务器。 当 Service2Bootstrap 启动后,应用 service2 将出现在 Nacos 控制台界面。
实现service1调用service2
引用service2
在service2中添加service1的依赖:
<dependency>
<groupId>com.itheima.nacos</groupId>
<artifactId>service‐2‐api</artifactId>
<version>1.0‐SNAPSHOT</version>
</dependency>
实现远程调用
@org.apache.dubbo.config.annotation.Service
public class ConsumerServiceImpl implements ConsumerService {
@Reference
ProviderService providerService;
public String service() {
return "Consumer invoke | "+providerService.service();
}
}
测试:
请求:http://localhost:56020/application1/service. application1调用service1,service1调用service2
实现api-gateway
什么是网关?
原来的单体架构,所有的服务都是本地的,UI可以直接调用,现在按功能拆分成独立的服务,跑在独立的一般都在 独立的虚拟机上的 Java进程了。客户端UI如何访问?他的后台有N个服务,前台就需要记住管理N个服务,一个服 务下线/更新/升级,前台就要重新部署,这明显不服务我们拆分的理念,特别当前台是移动应用的时候,通常业务 变化的节奏更快。另外,N个小服务的调用也是一个不小的网络开销。
有了网关作为服务统一入口,就可以避免上述问题,不仅如此,服务网关是在微服务前边设置一道屏障,请求先到 服务网关,网关会对请求进行过虑、校验、路由等处理。有了服务网关可以提高微服务的安全性,网关校验请求的 合法性,请求不合法将被拦截,拒绝访问。
- 提供统一服务入口,让微服务对前台透明
- 聚合后台的服务,节省流量,提升性能
- 提供安全,过滤,流控等API管理功能
- 上一篇: 香~Spring Boot 应用也可以有注册中心
- 下一篇: Nacos读取配置文件的顺序
猜你喜欢
- 2025-01-05 Nacos读取配置文件的顺序
- 2025-01-05 真香系列:聊聊SpringCloud Nacos服务配置中心
- 2025-01-05 香~Spring Boot 应用也可以有注册中心
- 2025-01-05 玩转Nacos参数配置!多图勿点
- 2025-01-05 关于研发规范化的一些实践和思考
- 2025-01-05 Nacos—服务注册中心原理总结
- 2025-01-05 SpringCloud之Nacos作为配置中心
- 2025-01-05 SpringCloud Alibaba的前世今生【面试必看】(5)
- 2025-01-05 Spring AI Alibaba 配置管理,用 Nacos 就够了
- 2025-01-05 Nacos 高级详解:提升你的开发和部署效率
你 发表评论:
欢迎- 368℃用AI Agent治理微服务的复杂性问题|QCon
- 366℃手把手教程「JavaWeb」优雅的SpringMvc+Mybatis整合之路
- 358℃初次使用IntelliJ IDEA新建Maven项目
- 351℃Maven技术方案最全手册(mavena)
- 348℃安利Touch Bar 专属应用,让闲置的Touch Bar活跃起来!
- 347℃InfoQ 2024 年趋势报告:架构篇(infoq+2024+年趋势报告:架构篇分析)
- 345℃IntelliJ IDEA 2018版本和2022版本创建 Maven 项目对比
- 343℃从头搭建 IntelliJ IDEA 环境(intellij idea建包)
- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)