# vertx-framework
**Repository Path**: javacoo/vertx-framework
## Basic Information
- **Project Name**: vertx-framework
- **Description**: 这是一个简单的响应式接口开发框架,基于对vertx的路由创建,服务注册,Verticle部署等基本操作的简单封装,让接口开发过程更接近于传统的开发模式,简化响应式接口开发流程,降低开发门槛。
框架目前接入了jdbc,redis,后续根据具体需要在接入其他组件,更多组件信息见:https://vertx.io/docs
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: feature
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2023-03-29
- **Last Updated**: 2024-11-29
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# vertx-framework
#### 介绍
这是一个简单的响应式接口开发框架,基于对vertx的路由创建,服务注册,Verticle部署等基本操作的简单封装,让接口开发过程更接近于传统的开发模式,简化响应式接口开发流程,降低开发门槛。
框架目前接入了jdbc,redis,后续根据具体需要在接入其他组件,更多组件信息见:https://vertx.io/docs
#### 软件架构
软件架构说明
#### 安装教程
1. 引入pom
```xml
org.javacoo.vertx
vertx-core
1.0
org.javacoo.vertx
vertx-database
1.0
```
#### 开发步骤
1. 配置文件:
主配置文件:application.yaml
```yaml
server:
port: 8080
contextPath: /
redis:
urls:
- redis://127.0.0.1:6379/0
clientType: STANDALONE
poolName: p-red
poolCleanerInterval: 30000
maxPoolSize: 8
maxPoolWaiting: 32
password: 1239abcz
vertx:
eventLoopPoolSize: 2
workerPoolSize: 4
eventBusOptions:
connectTimeout: 6000
vertxScan:
routerPackage: test.api.rest
servicePackage: test.api.service
serviceInstances: 1
```
环境配置文件:application-cloud.yaml
```yaml
env: cloud
dataSource:
driverClass: org.postgresql.Driver
url: jdbc:postgresql://127.0.0.1:9000/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2B8&tinyInt1isBit=false
user: postgres
password: 123456
maxPoolSize: 30
sqlConfig:
init: SELECT 1=1
# 总览-根据区域查询学校
getSchoolsInfoByArea: SELECT t.xxmc schoolName, t.xxdz schoolAddress, t.xxbsm schoolCode, t.jgjd longitude, t.jgwd latitude FROM gis_school_location t WHERE t.xxbxlx = !{eduType} AND t.area_code LIKE !{queryAreaCode} LIMIT !{pageSize} OFFSET !{offset}
```
2. 启动类
```java
public class ApiLauncher implements Launcher {
private static final Logger LOGGER = LoggerFactory.getLogger(ApiLauncher.class);
/**
* 环境
*/
private static String env = EnvEnum.CLOUD.getCode();
/**
* 服务端口
*/
private static int serverPort = Constant.HTTP_PORT;
private Vertx vertx;
@Override
public void start() {
Vertx tempVertx = Vertx.vertx();
// 加载配置
ConfigRetriever retriever = initConfigRetriever(tempVertx);
retriever.getConfig(json -> {
tempVertx.close();
if(json.succeeded()){
doStart(json);
}else{
LOGGER.error("加载配置");
}
});
}
/**
* 执行启动
*
* @author duanyong
* @date 2023/3/31 21:26
* @param json
* @return: void
*/
private void doStart(AsyncResult json){
JsonObject envConfig = json.result();
LOGGER.info("配置读取成功");
//默认读取dev开发环境配置
JsonObject vertxConfig = envConfig.getJsonObject("vertx");
Vertx mainVertx = Vertx.vertx(new VertxOptions(vertxConfig));
//初始化
VertxHolder.init(mainVertx);
//配置保存在共享数据中
SharedData sharedData = mainVertx.sharedData();
LocalMap localMap = sharedData.getLocalMap("/");
localMap.put("env", env);
localMap.put("envConfig", envConfig);
//先初始化再发布Http服务
mainVertx.executeBlocking(p -> {
//顺序不能乱
try {
//初始化ConfigProperties
ConfigPropertiesHolder.init(envConfig);
//初始化RedisClientHolder
RedisAPIHolder.init(mainVertx, envConfig, redisConnectionAsyncResult -> {
if(redisConnectionAsyncResult.succeeded()){
LOGGER.info("redis初始化成功");
}else{
LOGGER.error("redis初始化失败",redisConnectionAsyncResult.cause());
}
});
//初始化JDBCClient
JDBCClientHolder.init(envConfig, ready -> {
if (ready.succeeded()) {
p.complete();
LOGGER.info("JDBCClient初始化成功");
} else {
p.fail(ready.cause());
LOGGER.error("JDBCClient初始化失败",ready.cause());
}
});
} catch (Exception e) {
LOGGER.error("初始化失败:{}",e);
p.fail(e);
}
}).onComplete(ar2 -> {
if (ar2.succeeded()) {
JsonObject vertxScanConfig = envConfig.getJsonObject("vertxScan");
JsonObject serverConfig = envConfig.getJsonObject("server");
if(EnvEnum.CLOUD.getCode().equals(env)){
serverPort = serverConfig.getInteger("port");
}
LOGGER.info("准备启动服务,http服务端口:{}",serverPort);
EventConsumerConfig eventConsumerConfig = new EventConsumerConfig();
Router router = new RouterHandlerFactory(vertxScanConfig.getString("routerPackage"), serverConfig.getString("contextPath")).createRouter();
DeployVertxServer.startDeploy(eventConsumerConfig.consumer(),router, vertxScanConfig.getString("servicePackage"), serverPort, vertxScanConfig.getInteger("serviceInstances"));
} else {
LOGGER.error(ar2.cause().getMessage(), ar2.cause());
}
});
}
@Override
public void stop() {
vertx.close();
}
/**
* 初始化ConfigRetriever
*
* @author duanyong
* @date 2023/3/27 22:08
* @param vertx
* @return: ConfigRetriever
*/
private ConfigRetriever initConfigRetriever(Vertx vertx) {
//初始化
ConfigRetrieverOptions options = initOptions();
//创建
return ConfigRetriever.create(vertx, options);
}
/**
* 初始化ConfigRetrieverOptions
*
* @author duanyong
* @date 2023/3/27 23:08
* @return: ConfigRetrieverOptions
*/
private ConfigRetrieverOptions initOptions() {
// 使用默认ConfigStore
ConfigRetrieverOptions options = new ConfigRetrieverOptions().setIncludeDefaultStores(false);
// 禁用配置刷新
options.setScanPeriod(-1);
//加载主配置
options.addStore(new ConfigStoreOptions()
.setType("file")
.setFormat("yaml")
.setOptional(true)
.setConfig(new JsonObject().put("path", "application.yaml")));
String envFile = new StringBuilder("application-").append(env).append(".yaml").toString();
//加载环境配置
options.addStore(new ConfigStoreOptions()
.setType("file")
.setFormat("yaml")
.setOptional(true)
.setConfig(new JsonObject().put("path", envFile)));
// 禁用缓存
options.getStores().forEach(store -> {
store.getConfig().put("cache", "false");
});
return options;
}
public static void main(String[] args) {
if (args.length >= 1 && !CONFIG_DEFAULT.equals(args[0])) {
env = args[0];
}
if (args.length >= 2 && !CONFIG_DEFAULT.equals(args[1])) {
serverPort = Integer.valueOf(args[1]);
}
Launcher launcher = new GisApiLauncher();
launcher.start();
}
}
```
3. 编写服务
接口类:TestService
```java
/**
* 测试服务接口
*
*
* @author duanyong
* @version 1.0
* @date 2023/6/24 22:17
*/
@ProxyGen
@VertxGen
public interface TestService {
@GenIgnore
static test.api.reactivex.service.TestService createRxProxy() {
return new test.api.reactivex.service.TestService(AsyncServiceUtil.getAsyncServiceInstance(TestService.class));
}
/**
* 测试方法
*
* @author duanyong
* @date 2023/6/24 22:47
* @param query
* @param resultHandler
* @return: OverviewService
*/
@Fluent
TestService test(JsonObject query,Handler>> resultHandler);
}
```
实现类:TestServiceImpl
```java
/**
* 总览服务接口实现类
*
*
* @author duanyong
* @version 1.0
* @date 2023/6/24 23:20
*/
public class TestServiceImpl extends BaseAsyncService implements TestService {
protected ConfigProperties.SqlConfigProperties sqlConfig;
protected JDBCClient dbClient;
public OverviewServiceImpl() {
sqlConfig = ConfigPropertiesHolder.getConfigProperties().getSqlConfig();
dbClient = JDBCClientHolder.getJDBCClient();
}
@Override
public TestService test(JsonObject query, Handler>> resultHandler) {
String areaCode = getAreaCodePrefix(query);
String eduType = query.getString("eduType");
Integer pageSize = query.getInteger("pageSize");
Integer pageNum = query.getInteger("pageNum");
JsonObject result = parseTemplateSQL(sqlConfig.getGetSchoolsInfoByArea(),query);
String finalSql = result.getString(SQL_KEY);
JsonArray data = result.getJsonArray(PARAM_KEY);
String cacheKey = new StringBuilder("getSchoolsInfoByArea_").append(areaCode).append(eduType).append(pageSize).append(pageNum).toString();
loadListData(dbClient,resultHandler, finalSql, data, cacheKey);
return this;
}
}
```
4. 编写接口
```java
/**
* 测试服务接口
*
*
* @author duanyong
* @version 1.0
* @date 2023/6/25 22:27
*/
@RouteHandler
public class TestApi extends BaseRestApi {
/**
* 测试服务
*/
private TestService testService = test.api.service.TestService.createRxProxy();
/**
* 测试
* @return
*/
@RouteMapping(value = "/api/test", method = RouteMethod.POST)
public Handler test() {
return ctx -> {
JsonObject query = ctx.body().asJsonObject();
if (!validateJsonPageDocument(ctx, query, "areaCode","level")) {
return;
}
testService.rxTest(query)
.subscribe(totalList -> fireJsonResponse(ctx, new JsonResult(totalList)), t -> fireErrorJsonResponse(ctx, t.getMessage()));
};
}
}
```
至此便完成整个开发流程
#### 参与贡献
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)