package com.szmirren.vxApi.core.verticle; import java.text.MessageFormat; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.szmirren.vxApi.core.common.PathUtil; import com.szmirren.vxApi.core.common.StrUtil; import com.szmirren.vxApi.core.common.VxApiDATAStoreConstant; import com.szmirren.vxApi.core.common.VxApiEventBusAddressConstant; import com.szmirren.vxApi.core.common.VxApiGatewayAttribute; import io.vertx.core.AbstractVerticle; import io.vertx.core.Future; import io.vertx.core.eventbus.Message; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.ext.jdbc.JDBCClient; /** * 网关应用与API持久化的Verticle * * @author <a href="http://szmirren.com">Mirren</a> * */ public class DATAVerticle extends AbstractVerticle { private static final Logger LOG = LogManager.getLogger(DATAVerticle.class); /** * JDBC客户端 */ private JDBCClient jdbcClient = null; /** * 当前Vertx的唯一标识 */ private String thisVertxName; @Override public void start(Future<Void> fut) throws Exception { LOG.info("start DATA Verticle ..."); thisVertxName = System.getProperty("thisVertxName", "VX-API"); initShorthand();// 初始化简写后的常量数据 JsonObject dbConfig = config(); String url = dbConfig.getString("url"); if (dbConfig.getString("url").contains("jdbc:sqlite:")) { String temp = url.replace("jdbc:sqlite:", ""); if (temp.indexOf("/") < 0) { dbConfig.put("url", "jdbc:sqlite:" + PathUtil.getPathString(temp)); } } jdbcClient = JDBCClient.createShared(vertx, dbConfig, VxApiGatewayAttribute.NAME); // application operation address vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.FIND_APP, this::findApplication); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.GET_APP, this::getApplication); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.ADD_APP, this::addApplication); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.DEL_APP, this::delApplication); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.UPDT_APP, this::updtApplication); // api operation address vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.FIND_API_ALL, this::findAPI); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.FIND_API_BY_PAGE, this::findAPIByPage); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.GET_API, this::getAPI); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.ADD_API, this::addAPI); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.DEL_API, this::delAPI); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.UPDT_API, this::updtAPI); // blacklist vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.FIND_BLACKLIST, this::findBlacklist); vertx.eventBus().consumer(thisVertxName + VxApiEventBusAddressConstant.REPLACE_BLACKLIST, this::replaceBlacklist); LOG.info("start DATA Verticle successful"); fut.complete(); } // ============================================= // =====================网关应用================== // ============================================= /** * 网关应用的表名简写 */ private String APPTN = null; /** * 网关应用的主键列简写 */ private String APPIC = null; /** * 网关应用json字符串内容的列名简写 */ private String APPCC = null; /** * 网关应用通讯传输中获取json中存放主键的属性名简写 */ private String APPIN = null; /** * 网关应用通讯传输中获取json中存放json字符串对象的属性名简写 */ private String APPCN = null; /** * 获得所有应用程序 * * @param msg */ public void findApplication(Message<String> msg) { String sql = MessageFormat.format("select {0} AS {1} ,{2} AS {3} from {4} ", APPIC, APPIN, APPCC, APPCN, APPTN); jdbcClient.query(sql, res -> { if (res.succeeded()) { List<JsonObject> rows = res.result().getRows(); if (rows != null) { JsonArray array = new JsonArray(); rows.forEach(va -> { if (va.getValue(APPCN) instanceof String) { array.add(new JsonObject(va.getString(APPCN))); } else if (va.getValue(APPCN) instanceof JsonObject) { array.add(va.getJsonObject(APPCN)); } }); msg.reply(array); } else { msg.reply(new JsonArray()); } } else { msg.fail(500, res.cause().toString()); LOG.error("执行查询所有应用程序-->失败:" + res.cause().toString()); } }); } /** * 获得一个应用程序,接收应用程序的字符串名字 * * @param msg */ public void getApplication(Message<String> msg) { String name = msg.body(); if (name == null) { msg.fail(411, "the application name is null"); } else { String sql = MessageFormat.format("select {0} AS {1} ,{2} AS {3} from {4} where {0} = ? ", APPIC, APPIN, APPCC, APPCN, APPTN); JsonArray params = new JsonArray(); params.add(name); jdbcClient.queryWithParams(sql, params, res -> { if (res.succeeded()) { List<JsonObject> rows = res.result().getRows(); JsonObject result = null; if (rows != null && rows.size() > 0) { result = rows.get(0); } else { result = new JsonObject(); } msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行查询应用程序-->失败:" + res.cause().toString()); } }); } } /** * 添加应用程序,接收一个网关应用的json对象, * * @param msg */ public void addApplication(Message<JsonObject> msg) { if (msg.body() == null) { msg.fail(411, "the application options is null"); } else { JsonObject body = msg.body(); String sql = MessageFormat.format("insert into {0} ({1},{2}) values(?,?)", APPTN, APPIC, APPCC); JsonArray params = new JsonArray(); params.add(body.getString("appName")); params.add(body.getJsonObject("app").toString()); jdbcClient.updateWithParams(sql, params, res -> { if (res.succeeded()) { int result = res.result().getUpdated(); msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行添加应用程序-->失败:" + res.cause().toString()); } }); } } /** * 删除一个应用程序,接收应用程序的字符串名字 * * @param msg */ public void delApplication(Message<String> msg) { if (msg.body() == null) { msg.fail(411, "the application name is null"); } else { String isql = MessageFormat.format("delete from {0} where {1} = ?", APITN, API_APPIC); JsonArray iparams = new JsonArray(); iparams.add(msg.body()); jdbcClient.updateWithParams(isql, iparams, ires -> { if (ires.succeeded()) { String sql = MessageFormat.format("delete from {0} where {1} = ?", APPTN, APPIC); JsonArray params = new JsonArray(); params.add(msg.body()); jdbcClient.updateWithParams(sql, params, res -> { if (res.succeeded()) { int result = res.result().getUpdated(); msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行删除应用程序-->失败:" + ires.cause().toString()); } }); } else { msg.fail(500, ires.cause().toString()); LOG.error("执行删除应用程序-->失败:" + ires.cause().toString()); } }); } } /** * 修改应用程序,接收一个网关应用的json对象 * * @param msg */ public void updtApplication(Message<JsonObject> msg) { if (msg.body() == null) { msg.fail(411, "the application name is null"); } else { JsonObject body = msg.body(); String sql = MessageFormat.format("update {0} set {1}= ? where {2} = ?", APPTN, APPCC, APIIC); JsonArray params = new JsonArray(); params.add(body.getJsonObject("app").toString()); params.add(body.getString("appName")); jdbcClient.updateWithParams(sql, params, res -> { if (res.succeeded()) { int result = res.result().getUpdated(); msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行更新应用程序-->失败:" + res.cause().toString()); } }); } } // ============================================= // =====================APIS==================== // ============================================= /** * 存放API的表名简写 */ private String APITN = null; /** * 存放API的主键列简写 */ private String APIIC = null; /** * 存放API表中网关应用主键的列简写 */ private String API_APPIC = null; /** * 存放API,json字符串内容的列名简写 */ private String APICC = null; /** * API通讯传输中获取json中存放主键的属性名简写 */ private String APIIN = null; /** * API通讯传输中获取json中存放应用网关主键的属性名简写 */ private String API_APPIN = null; /** * API通讯传输中获取json中存放json字符串对象的属性名简写 */ private String APICN = null; /** * 查看所有API * * @param msg */ public void findAPI(Message<JsonObject> msg) { if (msg.body() == null || msg.body().getString("appName") == null) { msg.fail(411, "the application name is null"); } else { String sql = MessageFormat.format("select {0} AS {1},{2} AS {3},{4} AS {5} from {6} where {2} = ? ", APIIC, APIIN, API_APPIC, API_APPIN, APICC, APICN, APITN); // 添加从请求中获取添加值并添加到查询条件中 JsonArray params = new JsonArray(); params.add(msg.body().getString("appName")); jdbcClient.queryWithParams(sql, params, res -> { if (res.succeeded()) { List<JsonObject> rows = res.result().getRows(); JsonArray array = new JsonArray(); rows.forEach(va -> { if (va.getValue(APICN) instanceof String) { array.add(new JsonObject(va.getString(APICN))); } else if (va.getValue(APICN) instanceof JsonObject) { array.add(va.getJsonObject(APICN)); } }); msg.reply(array); } else { msg.fail(500, res.cause().toString()); LOG.error("执行查看所有API-->失败:" + res.cause().toString()); } }); } } /** * 获得一个应用的所有API,传入应用程序的name, * * @param msg */ public void findAPIByPage(Message<JsonObject> msg) { if (msg.body() == null) { msg.fail(411, "the application name is null"); } else { JsonObject body = msg.body(); String countSql = MessageFormat.format("select count({0}) from {1} where {2} = ? ", APIIC, APITN, API_APPIC); JsonArray countParams = new JsonArray(); countParams.add(body.getString("appName")); jdbcClient.queryWithParams(countSql, countParams, count -> { if (count.succeeded()) { Object value = count.result().getResults().get(0).getValue(0); long dataCount = ((Number) value).longValue(); // TODO 如果存储的数据库不支持limit 与offset 需要自己修改一下分页语句 String sql = MessageFormat.format("select {0} AS {1},{2} AS {3},{4} AS {5} from {6} where {2} = ? limit ? offset ?", APIIC, APIIN, API_APPIC, API_APPIN, APICC, APICN, APITN); JsonArray params = new JsonArray(); params.add(body.getString("appName")); params.add(body.getInteger("limit")); params.add(body.getInteger("offset")); jdbcClient.queryWithParams(sql, params, res -> { if (res.succeeded()) { List<JsonObject> rows = res.result().getRows(); JsonArray array = new JsonArray(); rows.forEach(va -> { if (va.getValue(APICN) instanceof String) { array.add(new JsonObject(va.getString(APICN))); } else if (va.getValue(APICN) instanceof JsonObject) { array.add(va.getJsonObject(APICN)); } }); msg.reply(new JsonObject().put("dataCount", dataCount).put("data", array)); } else { msg.fail(500, res.cause().toString()); LOG.error("执行查看所有API-->失败:" + res.cause().toString()); } }); } else { msg.fail(500, count.cause().toString()); LOG.error("执行查看所有API-->失败:" + count.cause().toString()); } }); } } /** * 获得一个api * * @param msg */ public void getAPI(Message<String> msg) { String name = msg.body(); if (name == null) { msg.fail(411, "the application name is null"); } else { String sql = MessageFormat.format("select {0} AS {1},{2} AS {3},{4} AS {5} from {6} where {0} = ? ", APIIC, APIIN, API_APPIC, API_APPIN, APICC, APICN, APITN); JsonArray params = new JsonArray(); params.add(name); jdbcClient.queryWithParams(sql, params, res -> { if (res.succeeded()) { List<JsonObject> rows = res.result().getRows(); JsonObject result = null; if (rows != null && rows.size() > 0) { result = rows.get(0); } else { result = new JsonObject(); } msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行查看API-->失败:" + res.cause().toString()); } }); } } /** * 添加API,接收一个json对象,对象包含该app应用appName,网关的json对象api * * @param msg */ public void addAPI(Message<JsonObject> msg) { if (msg.body() == null) { msg.fail(411, "the application options is null"); } else { JsonObject body = msg.body(); String appName = body.getString("appName"); Future<Void> addApiFuture = Future.future(); // 判断有没有存在该应用后执行 addApiFuture.setHandler(check -> { String sql = MessageFormat.format("insert into {0} ({1},{2},{3}) values(?,?,?)", APITN, APIIC, API_APPIC, APICC); JsonArray params = new JsonArray(); params.add(body.getString("apiName")); params.add(appName); params.add(body.getJsonObject("api").toString()); jdbcClient.updateWithParams(sql, params, res -> { if (res.succeeded()) { int result = res.result().getUpdated(); msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行添加API-->失败:" + res.cause().toString()); } }); }); String sql = MessageFormat.format("select {0} AS {1} ,{2} AS {3} from {4} where {0} = ? ", APPIC, APPIN, APPCC, APPCN, APPTN); JsonArray params = new JsonArray(); params.add(appName); jdbcClient.queryWithParams(sql, params, res -> { if (res.succeeded()) { List<JsonObject> rows = res.result().getRows(); if (rows != null && rows.size() > 0) { addApiFuture.complete(); } else { msg.fail(500, "网关应用不存在!"); LOG.debug("执行添加API->查询应用程序-->失败:网关应用不存在!"); } } else { msg.fail(500, res.cause().toString()); LOG.error("执行添加API->查询应用程序-->失败:" + res.cause().toString()); } }); } } /** * 删除一个API,接收应用程序的字符串名字 * * @param msg */ public void delAPI(Message<JsonObject> msg) { if (msg.body() == null) { msg.fail(411, "the msg body is null"); } else { String appName = msg.body().getString("appName"); String apiName = msg.body().getString("apiName"); if (StrUtil.isNullOrEmpty(appName, apiName)) { msg.fail(411, "the appName or apiName is null"); return; } String sql = MessageFormat.format("delete from {0} where {1} = ? and {2} = ? ", APITN, API_APPIC, APIIC); JsonArray params = new JsonArray(); params.add(appName); params.add(apiName); jdbcClient.updateWithParams(sql, params, res -> { if (res.succeeded()) { int result = res.result().getUpdated(); msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行删除API-->失败:" + res.cause().toString()); } }); } } /** * 修改API,接收一个json对象,其中包含主键name,内容content * * @param msg */ public void updtAPI(Message<JsonObject> msg) { if (msg.body() == null) { msg.fail(411, "the application name is null"); } else { JsonObject body = msg.body(); String sql = MessageFormat.format("update {0} set {1}= ? where {2} = ?", APITN, APICC, APIIC); JsonArray params = new JsonArray(); params.add(body.getJsonObject("api").toString()); params.add(body.getString("apiName")); jdbcClient.updateWithParams(sql, params, res -> { if (res.succeeded()) { int result = res.result().getUpdated(); msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行更新API-->失败:" + res.cause().toString()); } }); } } // ============================================= // =====================黑名单列表================= // ============================================= /** * 黑名单列表的表名简写 */ private String BLTN = null; /** * 黑名单列表的主键列简写 */ private String BLIC = null; /** * 黑名单列表jsonArray字符串内容的列名简写 */ private String BLCC = null; /** * 黑名单列表通讯传输中获取json中存放主键的属性名简写 */ private String BLIN = null; /** * 黑名单列表通讯传输中获取json中存放json字符串对象的属性名简写 */ private String BLCN = null; /** * 查看黑名单 * * @param msg */ public void findBlacklist(Message<JsonObject> msg) { String sql = MessageFormat.format("select {0} AS {1} ,{2} AS {3} from {4} ", BLIC, BLIN, BLCC, BLCN, BLTN); jdbcClient.query(sql, res -> { if (res.succeeded()) { List<JsonObject> rows = res.result().getRows(); JsonObject result = null; if (rows != null && rows.size() > 0) { result = rows.get(0); } else { result = new JsonObject(); } if (result.getValue(BLCN) instanceof String) { result.put(BLCN, new JsonArray(result.getString("content"))); } msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行查询应用程序-->失败:" + res.cause().toString()); } }); } /** * 更新黑名单 * * @param msg */ public void replaceBlacklist(Message<JsonObject> msg) { if (msg.body() == null) { msg.fail(412, "the Blacklist IP is null"); } else { JsonObject body = msg.body(); String sql = MessageFormat.format("REPLACE INTO {0} ({1},{2}) values(?,?)", BLTN, BLIC, BLCC); JsonArray params = new JsonArray(); params.add(body.getString("blacklistName")); params.add(body.getJsonArray("blacklistBody").toString()); jdbcClient.updateWithParams(sql, params, res -> { if (res.succeeded()) { int result = res.result().getUpdated(); msg.reply(result); } else { msg.fail(500, res.cause().toString()); LOG.error("执行添加应用程序-->失败:" + res.cause().toString()); } }); } } /** * 初始化简写后的常量数据 */ public void initShorthand() { this.APPTN = VxApiDATAStoreConstant.APPLICATION_TABLE_NAME; this.APPIC = VxApiDATAStoreConstant.APPLICATION_ID_COLUMN; this.APPCC = VxApiDATAStoreConstant.APPLICATION_CONTENT_COLUMN; this.APPIN = VxApiDATAStoreConstant.APPLICATION_ID_NAME; this.APPCN = VxApiDATAStoreConstant.APPLICATION_CONTENT_NAME; this.APITN = VxApiDATAStoreConstant.API_TABLE_NAME; this.APIIC = VxApiDATAStoreConstant.API_ID_COLUMN; this.APICC = VxApiDATAStoreConstant.API_CONTENT_COLUMN; this.APIIN = VxApiDATAStoreConstant.API_ID_NAME; this.APICN = VxApiDATAStoreConstant.API_CONTENT_NAME; this.API_APPIC = VxApiDATAStoreConstant.API_APP_ID_COLUMN; this.API_APPIN = VxApiDATAStoreConstant.API_APP_ID_NAME; this.BLTN = VxApiDATAStoreConstant.BLACKLIST_TABLE_NAME; this.BLIC = VxApiDATAStoreConstant.BLACKLIST_ID_COLUMN; this.BLCC = VxApiDATAStoreConstant.BLACKLIST_CONTENT_COLUMN; this.BLIN = VxApiDATAStoreConstant.BLACKLIST_ID_NAME; this.BLCN = VxApiDATAStoreConstant.BLACKLIST_CONTENT_NAME; } }