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 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