diff --git a/core-database/pom.xml b/core-database/pom.xml
new file mode 100644
index 0000000..c2b4c47
--- /dev/null
+++ b/core-database/pom.xml
@@ -0,0 +1,65 @@
+
+
+
+ lz-cow-api
+ cn.qaiu
+ 0.0.1
+
+ 4.0.0
+
+ core-database
+
+
+ 17
+ UTF-8
+ 2.0.5
+ 3.12.0
+ 4.4.1
+
+
+
+
+ cn.qaiu
+ core
+ 1.0.8
+
+
+
+
+ com.h2database
+ h2
+ 2.1.214
+
+
+
+
+ com.zaxxer
+ HikariCP
+ 5.0.1
+
+
+ org.apache.commons
+ commons-lang3
+ 3.12.0
+
+
+ io.vertx
+ vertx-codegen
+ compile
+ ${vertx.version}
+
+
+ io.vertx
+ vertx-sql-client-templates
+ ${vertx.version}
+
+
+ io.vertx
+ vertx-jdbc-client
+ ${vertx.version}
+
+
+
+
diff --git a/core-database/src/main/java/cn/qaiu/StartH2DatabaseServer.java b/core-database/src/main/java/cn/qaiu/StartH2DatabaseServer.java
new file mode 100644
index 0000000..5c52135
--- /dev/null
+++ b/core-database/src/main/java/cn/qaiu/StartH2DatabaseServer.java
@@ -0,0 +1,7 @@
+package cn.qaiu;
+
+public class StartH2DatabaseServer {
+ public static void main(String[] args) {
+ System.out.println("Hello world!");
+ }
+}
diff --git a/core-database/src/main/java/cn/qaiu/db/ddl/Constraint.java b/core-database/src/main/java/cn/qaiu/db/ddl/Constraint.java
new file mode 100644
index 0000000..3b234bf
--- /dev/null
+++ b/core-database/src/main/java/cn/qaiu/db/ddl/Constraint.java
@@ -0,0 +1,45 @@
+package cn.qaiu.db.ddl;
+
+import java.lang.annotation.*;
+
+/**
+ * 建表约束类型
+ *
+ *
Create date 2021/7/22 0:42
+ * @author QAIU
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.FIELD})
+public @interface Constraint {
+
+ /**
+ * 非空约束
+ * @return false 可以为空
+ */
+ boolean notNull() default false;
+
+ /**
+ * 唯一键约束 TODO 待实现
+ * @return 唯一键约束
+ */
+ String uniqueKey() default "";
+
+ /**
+ * 默认值约束
+ * @return 默认值约束
+ */
+ String defaultValue() default "";
+ /**
+ * 默认值是否是函数
+ * @return false 不是函数
+ */
+ boolean defaultValueIsFunction() default false;
+
+ /**
+ * 是否自增 只能用于int或long类型上
+ * @return false 不自增
+ */
+ boolean autoIncrement() default false;
+}
diff --git a/core-database/src/main/java/cn/qaiu/db/ddl/CreateTable.java b/core-database/src/main/java/cn/qaiu/db/ddl/CreateTable.java
new file mode 100644
index 0000000..063ad69
--- /dev/null
+++ b/core-database/src/main/java/cn/qaiu/db/ddl/CreateTable.java
@@ -0,0 +1,170 @@
+package cn.qaiu.db.ddl;
+
+import cn.qaiu.vx.core.util.ReflectionUtil;
+import io.vertx.codegen.format.CamelCase;
+import io.vertx.codegen.format.Case;
+import io.vertx.codegen.format.LowerCamelCase;
+import io.vertx.codegen.format.SnakeCase;
+import io.vertx.jdbcclient.JDBCPool;
+import io.vertx.sqlclient.templates.annotations.Column;
+import io.vertx.sqlclient.templates.annotations.RowMapped;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 创建表
+ *
+ * @author QAIU
+ */
+public class CreateTable {
+ public static Map, String> javaProperty2SqlColumnMap = new HashMap<>();
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CreateTable.class);
+
+ static {
+ javaProperty2SqlColumnMap.put(Integer.class, "INT");
+ javaProperty2SqlColumnMap.put(Short.class, "SMALLINT");
+ javaProperty2SqlColumnMap.put(Byte.class, "TINYINT");
+ javaProperty2SqlColumnMap.put(Long.class, "BIGINT");
+ javaProperty2SqlColumnMap.put(java.math.BigDecimal.class, "DECIMAL");
+ javaProperty2SqlColumnMap.put(Double.class, "DOUBLE");
+ javaProperty2SqlColumnMap.put(Float.class, "REAL");
+ javaProperty2SqlColumnMap.put(Boolean.class, "BOOLEAN");
+ javaProperty2SqlColumnMap.put(String.class, "VARCHAR");
+ javaProperty2SqlColumnMap.put(java.util.Date.class, "TIMESTAMP");
+ javaProperty2SqlColumnMap.put(java.sql.Timestamp.class, "TIMESTAMP");
+ javaProperty2SqlColumnMap.put(java.sql.Date.class, "DATE");
+ javaProperty2SqlColumnMap.put(java.sql.Time.class, "TIME");
+
+ javaProperty2SqlColumnMap.put(int.class, "INT");
+ javaProperty2SqlColumnMap.put(short.class, "SMALLINT");
+ javaProperty2SqlColumnMap.put(byte.class, "TINYINT");
+ javaProperty2SqlColumnMap.put(long.class, "BIGINT");
+ javaProperty2SqlColumnMap.put(double.class, "DOUBLE");
+ javaProperty2SqlColumnMap.put(float.class, "REAL");
+ javaProperty2SqlColumnMap.put(boolean.class, "BOOLEAN");
+ }
+
+ private static Case getCase(Class> clz) {
+ switch (clz.getName()) {
+ case "io.vertx.codegen.format.CamelCase":
+ return CamelCase.INSTANCE;
+ case "io.vertx.codegen.format.SnakeCase":
+ return SnakeCase.INSTANCE;
+ case "io.vertx.codegen.format.LowerCamelCase":
+ return LowerCamelCase.INSTANCE;
+ default:
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public static String getCreateTableSQL(Class> clz) {
+ // 判断类上是否有次注解
+ String primaryKey = null; // 主键
+ String tableName = null; // 表名
+ Case caseFormat = SnakeCase.INSTANCE;
+ if (clz.isAnnotationPresent(RowMapped.class)) {
+ RowMapped annotation = clz.getAnnotation(RowMapped.class);
+ Class extends Case> formatter = annotation.formatter();
+ caseFormat = getCase(formatter);
+ }
+
+ if (clz.isAnnotationPresent(Table.class)) {
+ // 获取类上的注解
+ Table annotation = clz.getAnnotation(Table.class);
+ // 输出注解上的类名
+ String tableNameAnnotation = annotation.value();
+ if (StringUtils.isNotEmpty(tableNameAnnotation)) {
+ tableName = tableNameAnnotation;
+ } else {
+ tableName = LowerCamelCase.INSTANCE.to(caseFormat, clz.getSimpleName());
+ }
+ primaryKey = annotation.keyFields();
+ }
+ Field[] fields = clz.getDeclaredFields();
+ String column;
+ int[] decimalSize = {22, 2};
+ int varcharSize = 255;
+ StringBuilder sb = new StringBuilder(50);
+ sb.append("CREATE TABLE IF NOT EXISTS \"").append(tableName).append("\" ( \r\n ");
+ boolean firstId = true;
+ for (Field f : fields) {
+ Class> paramType = f.getType();
+ String sqlType = javaProperty2SqlColumnMap.get(paramType);
+ if (f.getName().equals("serialVersionUID") || StringUtils.isEmpty(sqlType) || f.isAnnotationPresent(TableGenIgnore.class)) {
+ continue;
+ }
+ column = LowerCamelCase.INSTANCE.to(caseFormat, f.getName());
+ if (f.isAnnotationPresent(Column.class)) {
+ Column columnAnnotation = f.getAnnotation(Column.class);
+ //输出注解属性
+ if (StringUtils.isNotBlank(columnAnnotation.name())) {
+ column = columnAnnotation.name();
+ }
+ }
+ if (f.isAnnotationPresent(Length.class)) {
+ Length fieldAnnotation = f.getAnnotation(Length.class);
+ decimalSize = fieldAnnotation.decimalSize();
+ varcharSize = fieldAnnotation.varcharSize();
+ }
+ sb.append("\"").append(column).append("\"");
+ sb.append(" ").append(sqlType);
+ // 添加类型长度
+ if (sqlType.equals("DECIMAL")) {
+ sb.append("(").append(decimalSize[0]).append(",").append(decimalSize[1]).append(")");
+ }
+ if (sqlType.equals("VARCHAR")) {
+ sb.append("(").append(varcharSize).append(")");
+ }
+ if (f.isAnnotationPresent(Constraint.class)) {
+ Constraint constraintAnnotation = f.getAnnotation(Constraint.class);
+ if (constraintAnnotation.notNull()) {
+ //非空约束
+ sb.append(" NOT NULL");
+ }
+ String apostrophe = constraintAnnotation.defaultValueIsFunction() ? "" : "'";
+ if (StringUtils.isNotEmpty(constraintAnnotation.defaultValue())) {
+ //默认值约束
+ sb.append(" DEFAULT ").append(apostrophe).append(constraintAnnotation.defaultValue()).append(apostrophe);
+ }
+ if (constraintAnnotation.autoIncrement() && paramType.equals(Integer.class) || paramType.equals(Long.class)) {
+ ////自增
+ sb.append(" AUTO_INCREMENT");
+ }
+ }
+ if (StringUtils.isEmpty(primaryKey)) {
+ if (firstId) {//类型转换
+ sb.append(" PRIMARY KEY");
+ firstId = false;
+ }
+ } else {
+ if (primaryKey.equals(column.toLowerCase())) {
+ sb.append(" PRIMARY KEY");
+ }
+ }
+ sb.append(",\n ");
+ }
+ String sql = sb.toString();
+ //去掉最后一个逗号
+ int lastIndex = sql.lastIndexOf(",");
+ sql = sql.substring(0, lastIndex) + sql.substring(lastIndex + 1);
+ return sql.substring(0, sql.length() - 1) + ");\r\n";
+ }
+
+ public static void createTable(JDBCPool pool, String tableClassPath) {
+ Set> tableClassList = ReflectionUtil.getReflections(tableClassPath).getTypesAnnotatedWith(Table.class);
+ if (tableClassList.isEmpty()) LOGGER.info("Table model class not fount");
+ tableClassList.forEach(clazz -> {
+ String createTableSQL = getCreateTableSQL(clazz);
+ pool.query(createTableSQL).execute().onSuccess(
+ rs -> LOGGER.info("\n" + createTableSQL + "create table --> ok")
+ ).onFailure(Throwable::printStackTrace);
+ });
+ }
+}
diff --git a/core-database/src/main/java/cn/qaiu/db/ddl/Length.java b/core-database/src/main/java/cn/qaiu/db/ddl/Length.java
new file mode 100644
index 0000000..7962ee0
--- /dev/null
+++ b/core-database/src/main/java/cn/qaiu/db/ddl/Length.java
@@ -0,0 +1,16 @@
+package cn.qaiu.db.ddl;
+
+import java.lang.annotation.*;
+
+/**
+ * 字段长度属性
+ * @author QAIU
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.FIELD})
+public @interface Length {
+ int[] decimalSize() default {22,2}; //bigDecimal精度
+ int varcharSize() default 255; //varchar大小
+}
diff --git a/core-database/src/main/java/cn/qaiu/db/ddl/Table.java b/core-database/src/main/java/cn/qaiu/db/ddl/Table.java
new file mode 100644
index 0000000..ba1836d
--- /dev/null
+++ b/core-database/src/main/java/cn/qaiu/db/ddl/Table.java
@@ -0,0 +1,17 @@
+package cn.qaiu.db.ddl;
+
+import java.lang.annotation.*;
+
+/**
+ * 标注建表的实体类和主键字段
+ *
+ * @author QAIU
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.FIELD})//次注解作用于类和字段上
+public @interface Table {
+ String value() default ""; //默认表名为空
+ String keyFields() default "id"; //默认主键为id
+}
diff --git a/core-database/src/main/java/cn/qaiu/db/ddl/TableGenIgnore.java b/core-database/src/main/java/cn/qaiu/db/ddl/TableGenIgnore.java
new file mode 100644
index 0000000..2f4af30
--- /dev/null
+++ b/core-database/src/main/java/cn/qaiu/db/ddl/TableGenIgnore.java
@@ -0,0 +1,16 @@
+package cn.qaiu.db.ddl;
+
+import java.lang.annotation.*;
+
+/**
+ * 建表时忽略字段
+ *
Create date 2021/8/27 15:49
+ *
+ * @author QAIU
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.FIELD})
+public @interface TableGenIgnore {
+}
diff --git a/core-database/src/main/java/cn/qaiu/db/pool/JDBCPoolInit.java b/core-database/src/main/java/cn/qaiu/db/pool/JDBCPoolInit.java
new file mode 100644
index 0000000..ce32f56
--- /dev/null
+++ b/core-database/src/main/java/cn/qaiu/db/pool/JDBCPoolInit.java
@@ -0,0 +1,140 @@
+package cn.qaiu.db.pool;
+
+import cn.qaiu.db.ddl.CreateTable;
+import cn.qaiu.db.server.H2ServerHolder;
+import cn.qaiu.vx.core.util.VertxHolder;
+import io.vertx.core.Promise;
+import io.vertx.core.Vertx;
+import io.vertx.core.json.JsonObject;
+import io.vertx.jdbcclient.JDBCPool;
+import org.h2.tools.Server;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.SQLException;
+
+/**
+ * 初始化JDBC
+ *
Create date 2021/8/10 12:04
+ *
+ * @author QAIU
+ */
+public class JDBCPoolInit {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(JDBCPoolInit.class);
+ private JDBCPool pool = null;
+ JsonObject dbConfig;
+ Vertx vertx = VertxHolder.getVertxInstance();
+ String url;
+
+ private static JDBCPoolInit instance;
+
+ public JDBCPoolInit(Builder builder) {
+ this.dbConfig = builder.dbConfig;
+ this.url = builder.url;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static JDBCPoolInit instance() {
+ return instance;
+ }
+
+ public static class Builder {
+ private JsonObject dbConfig;
+ private String url;
+
+ public Builder config(JsonObject dbConfig) {
+ this.dbConfig = dbConfig;
+ this.url = dbConfig.getString("jdbcUrl");
+ return this;
+ }
+
+ public JDBCPoolInit build() {
+ if (JDBCPoolInit.instance == null) {
+ JDBCPoolInit.instance = new JDBCPoolInit(this);
+ }
+ return JDBCPoolInit.instance;
+ }
+ }
+
+
+ /**
+ * init h2db
+ * 这个方法只允许调用一次
+ */
+ public void initPool() {
+ if (pool != null) {
+ LOGGER.error("pool 重复初始化");
+ return;
+ }
+
+ // 异步启动H2服务
+ vertx.createSharedWorkerExecutor("h2-server", 1, Long.MAX_VALUE)
+ .executeBlocking(this::h2serverExecute)
+ .onSuccess(LOGGER::info)
+ .onFailure(Throwable::printStackTrace);
+
+ // 初始化数据库连接
+ vertx.createSharedWorkerExecutor("sql-pool-init")
+ .executeBlocking(this::poolInitExecute)
+ .onSuccess(LOGGER::info)
+ .onFailure(Throwable::printStackTrace);
+
+ }
+
+ private void poolInitExecute(Promise promise) {
+ // 初始化H2db, 创建本地db文件
+ LOGGER.info("init sql start");
+ String[] path = url.split("\\./");
+ path[1] = path[1].split(";")[0];
+ path[1] += ".mv.db";
+ File file = new File(path[1]);
+ if (!file.exists()) {
+ if (!file.getParentFile().exists()) {
+ if (file.getParentFile().mkdirs()) {
+ LOGGER.info("mkdirs -> {}", file.getParentFile().getAbsolutePath());
+ }
+ }
+ try {
+ if (file.createNewFile()) {
+ LOGGER.info("create file -> {}", file.getAbsolutePath());
+ }
+ } catch (IOException e) {
+ LOGGER.error(e.getMessage());
+ throw new RuntimeException("file create failed");
+ }
+ }
+ // 初始化连接池
+ pool = JDBCPool.pool(vertx, dbConfig);
+ CreateTable.createTable(pool, dbConfig.getString("tableClassPath"));
+ promise.complete("init jdbc pool success");
+
+ }
+
+ private void h2serverExecute(Promise promise) {
+ try {
+ String url = dbConfig.getString("jdbcUrl");
+ String[] portStr = url.split(":");
+ String port = portStr[portStr.length - 1].split("[/\\\\]")[0];
+ LOGGER.info("H2server listen port to {}", port);
+ H2ServerHolder.init(Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", port).start());
+ promise.complete("Start h2Server success");
+ } catch (SQLException e) {
+ throw new RuntimeException("Start h2Server failed: " + e.getMessage());
+ }
+ }
+
+ /**
+ * 获取连接池
+ *
+ * @return pool
+ */
+ public JDBCPool getPool() {
+ return pool;
+ }
+}
diff --git a/core-database/src/main/java/cn/qaiu/db/server/H2ServerHolder.java b/core-database/src/main/java/cn/qaiu/db/server/H2ServerHolder.java
new file mode 100644
index 0000000..5e2bb00
--- /dev/null
+++ b/core-database/src/main/java/cn/qaiu/db/server/H2ServerHolder.java
@@ -0,0 +1,26 @@
+package cn.qaiu.db.server;
+
+import org.h2.tools.Server;
+
+import java.util.Objects;
+
+/**
+ * h2db server
+ *
Create date 2021/7/23 2:44
+ *
+ * @author QAIU
+ */
+public class H2ServerHolder {
+
+ private static Server h2Server;
+
+ public static synchronized void init(Server server) {
+ Objects.requireNonNull(server, "未初始化h2Server");
+ h2Server = server;
+ }
+
+ public static Server getH2Server() {
+ Objects.requireNonNull(h2Server, "等待h2Server初始化");
+ return h2Server;
+ }
+}
diff --git a/lz-cow-api-web/pom.xml b/lz-cow-api-web/pom.xml
index 4de1019..0053f51 100644
--- a/lz-cow-api-web/pom.xml
+++ b/lz-cow-api-web/pom.xml
@@ -53,6 +53,12 @@
jsoup
1.15.4
+
+ cn.qaiu
+ core-database
+ 0.0.1
+ compile
+
diff --git a/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/DbServiceVertxEBProxy.java b/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/DbServiceVertxEBProxy.java
new file mode 100644
index 0000000..648d7cc
--- /dev/null
+++ b/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/DbServiceVertxEBProxy.java
@@ -0,0 +1,91 @@
+/*
+* Copyright 2014 Red Hat, Inc.
+*
+* Red Hat licenses this file to you under the Apache License, version 2.0
+* (the "License"); you may not use this file except in compliance with the
+* License. You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+*/
+
+package cn.qaiu.lz.web.service;
+
+import io.vertx.core.eventbus.DeliveryOptions;
+import io.vertx.core.Vertx;
+import io.vertx.core.Future;
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.function.Function;
+import io.vertx.serviceproxy.ServiceException;
+import io.vertx.serviceproxy.ServiceExceptionMessageCodec;
+import io.vertx.serviceproxy.ProxyUtils;
+
+import cn.qaiu.lz.common.model.UserInfo;
+import cn.qaiu.vx.core.base.BaseAsyncService;
+import io.vertx.core.Future;
+/*
+ Generated Proxy code - DO NOT EDIT
+ @author Roger the Robot
+*/
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class DbServiceVertxEBProxy implements DbService {
+ private Vertx _vertx;
+ private String _address;
+ private DeliveryOptions _options;
+ private boolean closed;
+
+ public DbServiceVertxEBProxy(Vertx vertx, String address) {
+ this(vertx, address, null);
+ }
+
+ public DbServiceVertxEBProxy(Vertx vertx, String address, DeliveryOptions options) {
+ this._vertx = vertx;
+ this._address = address;
+ this._options = options;
+ try {
+ this._vertx.eventBus().registerDefaultCodec(ServiceException.class, new ServiceExceptionMessageCodec());
+ } catch (IllegalStateException ex) {
+ }
+ }
+
+ @Override
+ public Future sayOk(String data){
+ if (closed) return io.vertx.core.Future.failedFuture("Proxy is closed");
+ JsonObject _json = new JsonObject();
+ _json.put("data", data);
+
+ DeliveryOptions _deliveryOptions = (_options != null) ? new DeliveryOptions(_options) : new DeliveryOptions();
+ _deliveryOptions.addHeader("action", "sayOk");
+ _deliveryOptions.getHeaders().set("action", "sayOk");
+ return _vertx.eventBus().request(_address, _json, _deliveryOptions).map(msg -> {
+ return msg.body();
+ });
+ }
+ @Override
+ public Future sayOk2(String data, UserInfo holder){
+ if (closed) return io.vertx.core.Future.failedFuture("Proxy is closed");
+ JsonObject _json = new JsonObject();
+ _json.put("data", data);
+ _json.put("holder", holder != null ? holder.toJson() : null);
+
+ DeliveryOptions _deliveryOptions = (_options != null) ? new DeliveryOptions(_options) : new DeliveryOptions();
+ _deliveryOptions.addHeader("action", "sayOk2");
+ _deliveryOptions.getHeaders().set("action", "sayOk2");
+ return _vertx.eventBus().request(_address, _json, _deliveryOptions).map(msg -> {
+ return msg.body();
+ });
+ }
+}
diff --git a/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/DbServiceVertxProxyHandler.java b/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/DbServiceVertxProxyHandler.java
new file mode 100644
index 0000000..a1d47d8
--- /dev/null
+++ b/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/DbServiceVertxProxyHandler.java
@@ -0,0 +1,140 @@
+/*
+* Copyright 2014 Red Hat, Inc.
+*
+* Red Hat licenses this file to you under the Apache License, version 2.0
+* (the "License"); you may not use this file except in compliance with the
+* License. You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+*/
+
+package cn.qaiu.lz.web.service;
+
+import cn.qaiu.lz.web.service.DbService;
+import io.vertx.core.Vertx;
+import io.vertx.core.Handler;
+import io.vertx.core.AsyncResult;
+import io.vertx.core.eventbus.EventBus;
+import io.vertx.core.eventbus.Message;
+import io.vertx.core.eventbus.MessageConsumer;
+import io.vertx.core.eventbus.DeliveryOptions;
+import io.vertx.core.eventbus.ReplyException;
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import io.vertx.serviceproxy.ProxyHandler;
+import io.vertx.serviceproxy.ServiceException;
+import io.vertx.serviceproxy.ServiceExceptionMessageCodec;
+import io.vertx.serviceproxy.HelperUtils;
+import io.vertx.serviceproxy.ServiceBinder;
+
+import cn.qaiu.lz.common.model.UserInfo;
+import cn.qaiu.vx.core.base.BaseAsyncService;
+import io.vertx.core.Future;
+/*
+ Generated Proxy code - DO NOT EDIT
+ @author Roger the Robot
+*/
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class DbServiceVertxProxyHandler extends ProxyHandler {
+
+ public static final long DEFAULT_CONNECTION_TIMEOUT = 5 * 60; // 5 minutes
+ private final Vertx vertx;
+ private final DbService service;
+ private final long timerID;
+ private long lastAccessed;
+ private final long timeoutSeconds;
+ private final boolean includeDebugInfo;
+
+ public DbServiceVertxProxyHandler(Vertx vertx, DbService service){
+ this(vertx, service, DEFAULT_CONNECTION_TIMEOUT);
+ }
+
+ public DbServiceVertxProxyHandler(Vertx vertx, DbService service, long timeoutInSecond){
+ this(vertx, service, true, timeoutInSecond);
+ }
+
+ public DbServiceVertxProxyHandler(Vertx vertx, DbService service, boolean topLevel, long timeoutInSecond){
+ this(vertx, service, true, timeoutInSecond, false);
+ }
+
+ public DbServiceVertxProxyHandler(Vertx vertx, DbService service, boolean topLevel, long timeoutSeconds, boolean includeDebugInfo) {
+ this.vertx = vertx;
+ this.service = service;
+ this.includeDebugInfo = includeDebugInfo;
+ this.timeoutSeconds = timeoutSeconds;
+ try {
+ this.vertx.eventBus().registerDefaultCodec(ServiceException.class,
+ new ServiceExceptionMessageCodec());
+ } catch (IllegalStateException ex) {}
+ if (timeoutSeconds != -1 && !topLevel) {
+ long period = timeoutSeconds * 1000 / 2;
+ if (period > 10000) {
+ period = 10000;
+ }
+ this.timerID = vertx.setPeriodic(period, this::checkTimedOut);
+ } else {
+ this.timerID = -1;
+ }
+ accessed();
+ }
+
+
+ private void checkTimedOut(long id) {
+ long now = System.nanoTime();
+ if (now - lastAccessed > timeoutSeconds * 1000000000) {
+ close();
+ }
+ }
+
+ @Override
+ public void close() {
+ if (timerID != -1) {
+ vertx.cancelTimer(timerID);
+ }
+ super.close();
+ }
+
+ private void accessed() {
+ this.lastAccessed = System.nanoTime();
+ }
+
+ public void handle(Message msg) {
+ try{
+ JsonObject json = msg.body();
+ String action = msg.headers().get("action");
+ if (action == null) throw new IllegalStateException("action not specified");
+ accessed();
+ switch (action) {
+ case "sayOk": {
+ service.sayOk((java.lang.String)json.getValue("data")).onComplete(HelperUtils.createHandler(msg, includeDebugInfo));
+ break;
+ }
+ case "sayOk2": {
+ service.sayOk2((java.lang.String)json.getValue("data"),
+ json.getJsonObject("holder") != null ? new cn.qaiu.lz.common.model.UserInfo((JsonObject)json.getJsonObject("holder")) : null).onComplete(HelperUtils.createHandler(msg, includeDebugInfo));
+ break;
+ }
+ default: throw new IllegalStateException("Invalid action: " + action);
+ }
+ } catch (Throwable t) {
+ if (includeDebugInfo) msg.reply(new ServiceException(500, t.getMessage(), HelperUtils.generateDebugInfo(t)));
+ else msg.reply(new ServiceException(500, t.getMessage()));
+ throw t;
+ }
+ }
+}
\ No newline at end of file
diff --git a/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/UserServiceVertxEBProxy.java b/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/UserServiceVertxEBProxy.java
new file mode 100644
index 0000000..c5ab8ea
--- /dev/null
+++ b/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/UserServiceVertxEBProxy.java
@@ -0,0 +1,77 @@
+/*
+* Copyright 2014 Red Hat, Inc.
+*
+* Red Hat licenses this file to you under the Apache License, version 2.0
+* (the "License"); you may not use this file except in compliance with the
+* License. You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+*/
+
+package cn.qaiu.lz.web.service;
+
+import io.vertx.core.eventbus.DeliveryOptions;
+import io.vertx.core.Vertx;
+import io.vertx.core.Future;
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.function.Function;
+import io.vertx.serviceproxy.ServiceException;
+import io.vertx.serviceproxy.ServiceExceptionMessageCodec;
+import io.vertx.serviceproxy.ProxyUtils;
+
+import cn.qaiu.lz.web.model.RealUser;
+import cn.qaiu.vx.core.base.BaseAsyncService;
+import io.vertx.core.Future;
+/*
+ Generated Proxy code - DO NOT EDIT
+ @author Roger the Robot
+*/
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class UserServiceVertxEBProxy implements UserService {
+ private Vertx _vertx;
+ private String _address;
+ private DeliveryOptions _options;
+ private boolean closed;
+
+ public UserServiceVertxEBProxy(Vertx vertx, String address) {
+ this(vertx, address, null);
+ }
+
+ public UserServiceVertxEBProxy(Vertx vertx, String address, DeliveryOptions options) {
+ this._vertx = vertx;
+ this._address = address;
+ this._options = options;
+ try {
+ this._vertx.eventBus().registerDefaultCodec(ServiceException.class, new ServiceExceptionMessageCodec());
+ } catch (IllegalStateException ex) {
+ }
+ }
+
+ @Override
+ public Future login(RealUser user){
+ if (closed) return io.vertx.core.Future.failedFuture("Proxy is closed");
+ JsonObject _json = new JsonObject();
+ _json.put("user", user != null ? user.toJson() : null);
+
+ DeliveryOptions _deliveryOptions = (_options != null) ? new DeliveryOptions(_options) : new DeliveryOptions();
+ _deliveryOptions.addHeader("action", "login");
+ _deliveryOptions.getHeaders().set("action", "login");
+ return _vertx.eventBus().request(_address, _json, _deliveryOptions).map(msg -> {
+ return msg.body();
+ });
+ }
+}
diff --git a/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/UserServiceVertxProxyHandler.java b/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/UserServiceVertxProxyHandler.java
new file mode 100644
index 0000000..4b430ac
--- /dev/null
+++ b/lz-cow-api-web/src/main/generated/cn/qaiu/lz/web/service/UserServiceVertxProxyHandler.java
@@ -0,0 +1,135 @@
+/*
+* Copyright 2014 Red Hat, Inc.
+*
+* Red Hat licenses this file to you under the Apache License, version 2.0
+* (the "License"); you may not use this file except in compliance with the
+* License. You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+*/
+
+package cn.qaiu.lz.web.service;
+
+import cn.qaiu.lz.web.service.UserService;
+import io.vertx.core.Vertx;
+import io.vertx.core.Handler;
+import io.vertx.core.AsyncResult;
+import io.vertx.core.eventbus.EventBus;
+import io.vertx.core.eventbus.Message;
+import io.vertx.core.eventbus.MessageConsumer;
+import io.vertx.core.eventbus.DeliveryOptions;
+import io.vertx.core.eventbus.ReplyException;
+import io.vertx.core.json.JsonObject;
+import io.vertx.core.json.JsonArray;
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import io.vertx.serviceproxy.ProxyHandler;
+import io.vertx.serviceproxy.ServiceException;
+import io.vertx.serviceproxy.ServiceExceptionMessageCodec;
+import io.vertx.serviceproxy.HelperUtils;
+import io.vertx.serviceproxy.ServiceBinder;
+
+import cn.qaiu.lz.web.model.RealUser;
+import cn.qaiu.vx.core.base.BaseAsyncService;
+import io.vertx.core.Future;
+/*
+ Generated Proxy code - DO NOT EDIT
+ @author Roger the Robot
+*/
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class UserServiceVertxProxyHandler extends ProxyHandler {
+
+ public static final long DEFAULT_CONNECTION_TIMEOUT = 5 * 60; // 5 minutes
+ private final Vertx vertx;
+ private final UserService service;
+ private final long timerID;
+ private long lastAccessed;
+ private final long timeoutSeconds;
+ private final boolean includeDebugInfo;
+
+ public UserServiceVertxProxyHandler(Vertx vertx, UserService service){
+ this(vertx, service, DEFAULT_CONNECTION_TIMEOUT);
+ }
+
+ public UserServiceVertxProxyHandler(Vertx vertx, UserService service, long timeoutInSecond){
+ this(vertx, service, true, timeoutInSecond);
+ }
+
+ public UserServiceVertxProxyHandler(Vertx vertx, UserService service, boolean topLevel, long timeoutInSecond){
+ this(vertx, service, true, timeoutInSecond, false);
+ }
+
+ public UserServiceVertxProxyHandler(Vertx vertx, UserService service, boolean topLevel, long timeoutSeconds, boolean includeDebugInfo) {
+ this.vertx = vertx;
+ this.service = service;
+ this.includeDebugInfo = includeDebugInfo;
+ this.timeoutSeconds = timeoutSeconds;
+ try {
+ this.vertx.eventBus().registerDefaultCodec(ServiceException.class,
+ new ServiceExceptionMessageCodec());
+ } catch (IllegalStateException ex) {}
+ if (timeoutSeconds != -1 && !topLevel) {
+ long period = timeoutSeconds * 1000 / 2;
+ if (period > 10000) {
+ period = 10000;
+ }
+ this.timerID = vertx.setPeriodic(period, this::checkTimedOut);
+ } else {
+ this.timerID = -1;
+ }
+ accessed();
+ }
+
+
+ private void checkTimedOut(long id) {
+ long now = System.nanoTime();
+ if (now - lastAccessed > timeoutSeconds * 1000000000) {
+ close();
+ }
+ }
+
+ @Override
+ public void close() {
+ if (timerID != -1) {
+ vertx.cancelTimer(timerID);
+ }
+ super.close();
+ }
+
+ private void accessed() {
+ this.lastAccessed = System.nanoTime();
+ }
+
+ public void handle(Message msg) {
+ try{
+ JsonObject json = msg.body();
+ String action = msg.headers().get("action");
+ if (action == null) throw new IllegalStateException("action not specified");
+ accessed();
+ switch (action) {
+ case "login": {
+ service.login(json.getJsonObject("user") != null ? new cn.qaiu.lz.web.model.RealUser((JsonObject)json.getJsonObject("user")) : null).onComplete(HelperUtils.createHandler(msg, includeDebugInfo));
+ break;
+ }
+ default: throw new IllegalStateException("Invalid action: " + action);
+ }
+ } catch (Throwable t) {
+ if (includeDebugInfo) msg.reply(new ServiceException(500, t.getMessage(), HelperUtils.generateDebugInfo(t)));
+ else msg.reply(new ServiceException(500, t.getMessage()));
+ throw t;
+ }
+ }
+}
\ No newline at end of file
diff --git a/lz-cow-api-web/src/main/java/cn/qaiu/lz/AppMain.java b/lz-cow-api-web/src/main/java/cn/qaiu/lz/AppMain.java
index c47f966..a7f5acd 100644
--- a/lz-cow-api-web/src/main/java/cn/qaiu/lz/AppMain.java
+++ b/lz-cow-api-web/src/main/java/cn/qaiu/lz/AppMain.java
@@ -1,9 +1,7 @@
package cn.qaiu.lz;
import cn.qaiu.vx.core.Deploy;
-import cn.qaiu.vx.core.util.VertxHolder;
import io.vertx.core.json.JsonObject;
-import lombok.val;
/**
@@ -15,15 +13,16 @@ import lombok.val;
public class AppMain {
public static void main(String[] args) {
- // 注册枚举类型转换器
Deploy.instance().start(args, AppMain::exec);
}
/**
+ * 初始化数据库
*
* @param jsonObject 配置
*/
private static void exec(JsonObject jsonObject) {
+// JDBCPoolInit.builder().config(jsonObject.getJsonObject("dataSource")).build().initPool();
}
diff --git a/lz-cow-api-web/src/main/java/cn/qaiu/lz/web/model/RealUser.java b/lz-cow-api-web/src/main/java/cn/qaiu/lz/web/model/RealUser.java
index 61e07ef..16db7e4 100644
--- a/lz-cow-api-web/src/main/java/cn/qaiu/lz/web/model/RealUser.java
+++ b/lz-cow-api-web/src/main/java/cn/qaiu/lz/web/model/RealUser.java
@@ -1,5 +1,6 @@
package cn.qaiu.lz.web.model;
+import cn.qaiu.db.ddl.Table;
import cn.qaiu.lz.common.ToJson;
import io.vertx.codegen.annotations.DataObject;
import io.vertx.core.json.JsonObject;
@@ -11,7 +12,10 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@DataObject
+@Table("t_user")
public class RealUser implements ToJson {
+ private String id;
+
private String username;
private String password;
diff --git a/lz-cow-api-web/src/main/resources/1.http b/lz-cow-api-web/src/main/resources/1.http
index 555b552..1b29e34 100644
--- a/lz-cow-api-web/src/main/resources/1.http
+++ b/lz-cow-api-web/src/main/resources/1.http
@@ -35,4 +35,8 @@ https://cowtransfer.com/core/api/transfer/share/download?transferGuid=e4f41b51-b
//https://download.cowcs.com/cowtransfer/cowtransfer/29188/db32e132e69f490eb4a343b398990f4b.docx?auth_key=1682111861-7b9579fbebb84aaba6bca368d083ab12-0-cbf009f3ffbcbb86191b8cdbc103abce&biz_type=1&business_code=COW_TRANSFER&channel_code=COW_CN_WEB&response-content-disposition=attachment%3B%20filename%3D05-CGB-DB-MENU-V1.02.docx%3Bfilename*%3Dutf-8%27%2705-CGB-DB-MENU-V1.02.docx&user_id=1023860921943729188&x-verify=1
+#V2 api
+###
+https://cowtransfer.com/core/api/dam/asset/files/download/23890683765739569/url/v2
+authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJndWlkIjoiMDc1OTMwNGItMDEwZS00MGJiLTlhNDUtZTczY2Q5ODYzMDQwIiwiZXhwIjoxNjgzNzkzOTExfQ.rE9z0vhogPjUC0I92MqU8U_PKe4j_mGn7lGgPFMGt5c
diff --git a/lz-cow-api-web/src/main/resources/logback.xml b/lz-cow-api-web/src/main/resources/logback.xml
index 289db29..3745f53 100644
--- a/lz-cow-api-web/src/main/resources/logback.xml
+++ b/lz-cow-api-web/src/main/resources/logback.xml
@@ -54,7 +54,7 @@
-
-
+
+
diff --git a/pom.xml b/pom.xml
index 52eece4..15c4ba2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,6 +12,7 @@
core
lz-cow-api-web
+ core-database