Skip to content

Commit 85f6b89

Browse files
committed
整合 apijson-router
1 parent d54042a commit 85f6b89

File tree

7 files changed

+888
-104
lines changed

7 files changed

+888
-104
lines changed

src/main/java/apijson/framework/APIJSONApplication.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ public static <T, M extends Map<String, Object>, L extends List<Object>> void in
7777
APIJSONSQLConfig.APIJSON_CREATOR = creator;
7878
APIJSONParser.APIJSON_CREATOR = creator;
7979
APIJSONController.APIJSON_CREATOR = creator;
80-
80+
APIJSONVerifier.APIJSON_CREATOR = creator;
81+
APIJSONFunctionParser.APIJSON_CREATOR = creator;
8182

8283
if (APIJSONVerifier.ENABLE_VERIFY_ROLE) {
8384
System.out.println("\n\n\n开始初始化: Access 权限校验配置 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
@@ -142,6 +143,18 @@ public static <T, M extends Map<String, Object>, L extends List<Object>> void in
142143
System.out.println("\n完成测试: Request 请求参数校验 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
143144
}
144145

146+
if (APIJSONVerifier.ENABLE_APIJSON_ROUTER) {
147+
System.out.println("\n\n\n开始初始化: Document 请求映射配置 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
148+
try {
149+
APIJSONVerifier.initDocument(shutdownWhenServerError, creator);
150+
} catch (Throwable e) {
151+
e.printStackTrace();
152+
if (shutdownWhenServerError) {
153+
onServerError("Document 请求映射配置 初始化失败!", shutdownWhenServerError);
154+
}
155+
}
156+
System.out.println("\n完成初始化: Document 请求映射配置 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
157+
}
145158

146159

147160
System.out.println("官方网站: http://apijson.cn");

src/main/java/apijson/framework/APIJSONController.java

Lines changed: 216 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,15 @@
1515
package apijson.framework;
1616

1717
import apijson.*;
18-
import apijson.orm.AbstractParser;
19-
import apijson.orm.Parser;
20-
import apijson.orm.Visitor;
18+
import apijson.JSONRequest;
19+
import apijson.orm.*;
2120

2221
import jakarta.servlet.http.HttpSession;
2322

2423
import java.rmi.ServerException;
25-
import java.util.List;
26-
import java.util.Map;
24+
import java.util.*;
2725

28-
import static apijson.JSON.toJSONString;
26+
import static apijson.JSON.*;
2927
import static apijson.RequestMethod.*;
3028
import static apijson.framework.APIJSONConstant.*;
3129

@@ -283,6 +281,218 @@ public String putByTag(String tag, Map<String, String> params, String request, H
283281
public String deleteByTag(String tag, Map<String, String> params, String request, HttpSession session) {
284282
return parseByTag(DELETE, tag, params, request, session);
285283
}
284+
//通用接口,非事务型操作 和 简单事务型操作 都可通过这些接口自动化实现<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
285+
286+
/**增删改查统一的类 RESTful API 入口,牺牲一些路由解析性能来提升一点开发效率
287+
* compatCommonAPI = Log.DEBUG
288+
* @param method
289+
* @param tag
290+
* @param params
291+
* @param request
292+
* @param session
293+
* @return
294+
*/
295+
public String router(String method, String tag, Map<String, String> params, String request, HttpSession session) {
296+
return router(method, tag, params, request, session, Log.DEBUG);
297+
}
298+
/**增删改查统一的类 RESTful API 入口,牺牲一些路由解析性能来提升一点开发效率
299+
* @param method
300+
* @param tag
301+
* @param params
302+
* @param request
303+
* @param session
304+
* @param compatCommonAPI 兼容万能通用 API,当没有映射 APIJSON 格式请求时,自动转到万能通用 API
305+
* @return
306+
*/
307+
public String router(String method, String tag, Map<String, String> params, String request, HttpSession session, boolean compatCommonAPI) {
308+
RequestMethod requestMethod = null;
309+
try {
310+
requestMethod = RequestMethod.valueOf(method.toUpperCase());
311+
} catch (Throwable e) {
312+
// 下方 METHODS.contains(method) 会抛异常
313+
}
314+
Parser<T, M, L> parser = newParser(session, requestMethod);
315+
316+
if (METHODS.contains(method) == false) {
317+
return JSON.toJSONString(
318+
parser.newErrorResult(
319+
new IllegalArgumentException("URL 路径 /{method}/{tag} 中 method 值 "
320+
+ method + " 错误!只允许 " + METHODS + " 中的一个!"
321+
)
322+
)
323+
);
324+
}
325+
326+
String t = compatCommonAPI && tag != null && tag.endsWith("[]") ? tag.substring(0, tag.length() - 2) : tag;
327+
if (StringUtil.isName(t) == false) {
328+
return JSON.toJSONString(
329+
parser.newErrorResult(
330+
new IllegalArgumentException("URL 路径 /" + method + "/{tag} 的 tag 中 "
331+
+ t + " 错误!tag 不能为空,且只允许变量命名格式!"
332+
)
333+
)
334+
);
335+
}
336+
337+
String versionStr = params == null ? null : params.remove(APIJSONConstant.VERSION);
338+
Integer version;
339+
try {
340+
version = StringUtil.isEmpty(versionStr, false) ? null : Integer.valueOf(versionStr);
341+
}
342+
catch (Exception e) {
343+
return JSON.toJSONString(
344+
parser.newErrorResult(new IllegalArgumentException("URL 路径 /" + method + "/"
345+
+ tag + "?version=value 中 value 值 " + versionStr + " 错误!必须符合整数格式!")
346+
)
347+
);
348+
}
349+
350+
if (version == null) {
351+
version = 0;
352+
}
353+
354+
try {
355+
// 从 Document 查这样的接口
356+
String cacheKey = AbstractVerifier.getCacheKeyForRequest(method, tag);
357+
SortedMap<Integer, Map<String, Object>> versionedMap = APIJSONVerifier.DOCUMENT_MAP.get(cacheKey);
358+
359+
Map<String, Object> result = versionedMap == null ? null : versionedMap.get(version);
360+
if (result == null) { // version <= 0 时使用最新,version > 0 时使用 > version 的最接近版本(最小版本)
361+
Set<Map.Entry<Integer, Map<String, Object>>> set = versionedMap == null ? null : versionedMap.entrySet();
362+
363+
if (set != null && set.isEmpty() == false) {
364+
Map.Entry<Integer, Map<String, Object>> maxEntry = null;
365+
366+
for (Map.Entry<Integer, Map<String, Object>> entry : set) {
367+
if (entry == null || entry.getKey() == null || entry.getValue() == null) {
368+
continue;
369+
}
370+
371+
if (version == null || version <= 0 || version == entry.getKey()) { // 这里应该不会出现相等,因为上面 versionedMap.get(Integer.valueOf(version))
372+
maxEntry = entry;
373+
break;
374+
}
375+
376+
if (entry.getKey() < version) {
377+
break;
378+
}
379+
380+
maxEntry = entry;
381+
}
382+
383+
result = maxEntry == null ? null : maxEntry.getValue();
384+
}
385+
386+
if (result != null) { // 加快下次查询,查到值的话组合情况其实是有限的,不属于恶意请求
387+
if (versionedMap == null) {
388+
versionedMap = new TreeMap<>((o1, o2) -> {
389+
return o2 == null ? -1 : o2.compareTo(o1); // 降序
390+
});
391+
}
392+
393+
versionedMap.put(version, result);
394+
APIJSONVerifier.DOCUMENT_MAP.put(cacheKey, versionedMap);
395+
}
396+
}
397+
398+
@SuppressWarnings("unchecked")
399+
APIJSONCreator<T, M, L> creator = (APIJSONCreator<T, M, L>) APIJSONParser.APIJSON_CREATOR;
400+
if (result == null && Log.DEBUG && APIJSONVerifier.DOCUMENT_MAP.isEmpty()) {
401+
402+
//获取指定的JSON结构 <<<<<<<<<<<<<<
403+
SQLConfig<T, M, L> config = creator.createSQLConfig().setMethod(GET).setTable(APIJSONConstant.DOCUMENT_);
404+
config.setPrepared(false);
405+
config.setColumn(Arrays.asList("request,apijson"));
406+
407+
Map<String, Object> where = new HashMap<String, Object>();
408+
where.put("url", "/" + method + "/" + tag);
409+
where.put("apijson{}", "length(apijson)>0");
410+
411+
if (version > 0) {
412+
where.put(JSONRequest.KEY_VERSION + ">=", version);
413+
}
414+
config.setWhere(where);
415+
config.setOrder(JSONRequest.KEY_VERSION + (version > 0 ? "+" : "-"));
416+
config.setCount(1);
417+
418+
//too many connections error: 不try-catch,可以让客户端看到是服务器内部异常
419+
result = creator.createSQLExecutor().execute(config, false);
420+
421+
// version, method, tag 组合情况太多了,JDK 里又没有 LRUCache,所以要么启动时一次性缓存全部后面只用缓存,要么每次都查数据库
422+
// versionedMap.put(Integer.valueOf(version), result);
423+
// DOCUMENT_MAP.put(cacheKey, versionedMap);
424+
}
425+
426+
String apijson = result == null ? null : getString(result, "apijson");
427+
if (StringUtil.isEmpty(apijson, true)) { //
428+
if (compatCommonAPI) {
429+
return crudByTag(method, tag, params, request, session);
430+
}
431+
432+
throw new IllegalArgumentException("URL 路径 /" + method
433+
+ "/" + tag + (versionStr == null ? "" : "?version=" + versionStr) + " 对应的接口不存在!");
434+
}
435+
436+
M rawReq = JSON.parseObject(request);
437+
if (rawReq == null) {
438+
rawReq = JSON.createJSONObject();
439+
}
440+
if (params != null && params.isEmpty() == false) {
441+
rawReq.putAll(params);
442+
}
443+
444+
if (parser.isNeedVerifyContent()) {
445+
Verifier<T, M, L> verifier = creator.createVerifier();
446+
447+
//获取指定的JSON结构 <<<<<<<<<<<<
448+
Map<String, Object> target = parser.getStructure("Request", method.toUpperCase(), tag, version);
449+
if (target == null) { //empty表示随意操作 || object.isEmpty()) {
450+
throw new UnsupportedOperationException("找不到 version: " + version + ", method: " + method.toUpperCase() + ", tag: " + tag + " 对应的 structure !"
451+
+ "非开放请求必须是后端 Request 表中校验规则允许的操作!如果需要则在 Request 表中新增配置!");
452+
}
453+
454+
//M clone 浅拷贝没用,Structure.parse 会导致 structure 里面被清空,第二次从缓存里取到的就是 {}
455+
verifier.verifyRequest(requestMethod, "", JSON.createJSONObject(target), rawReq, 0, null, null, creator);
456+
}
457+
458+
M apijsonReq = JSON.parseObject(apijson);
459+
if (apijsonReq == null) {
460+
apijsonReq = JSON.createJSONObject();
461+
}
462+
463+
Set<Map.Entry<String, Object>> rawSet = rawReq.entrySet();
464+
if (rawSet != null && rawSet.isEmpty() == false) {
465+
for (Map.Entry<String, Object> entry : rawSet) {
466+
String key = entry == null ? null : entry.getKey();
467+
if (key == null) { // value 为 null 有效
468+
continue;
469+
}
470+
471+
String[] pathKeys = key.split("\\.");
472+
//逐层到达child的直接容器JSONObject parent
473+
int last = pathKeys.length - 1;
474+
M parent = apijsonReq;
475+
for (int i = 0; i < last; i++) {//一步一步到达指定位置
476+
M p = getJSONObject(parent, pathKeys[i]);
477+
if (p == null) {
478+
p = JSON.createJSONObject();
479+
parent.put(key, p);
480+
}
481+
parent = p;
482+
}
483+
484+
parent.put(pathKeys[last], entry.getValue());
485+
}
486+
}
487+
488+
// 没必要,已经是预设好的实际参数了,如果要 tag 就在 apijson 字段配置 apijsonReq.put(JSONRequest.KEY_TAG, tag);
489+
490+
return parser.setNeedVerifyContent(false).parse(apijsonReq);
491+
}
492+
catch (Exception e) {
493+
return JSON.toJSONString(parser.newErrorResult(e));
494+
}
495+
}
286496

287497
//通用接口,非事务型操作 和 简单事务型操作 都可通过这些接口自动化实现>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
288498

src/main/java/apijson/framework/APIJSONCreator.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,8 @@
1414

1515
package apijson.framework;
1616

17-
import apijson.orm.FunctionParser;
18-
import apijson.orm.Parser;
1917
import apijson.orm.ParserCreator;
20-
import apijson.orm.SQLConfig;
2118
import apijson.orm.SQLCreator;
22-
import apijson.orm.SQLExecutor;
23-
import apijson.orm.Verifier;
2419
import apijson.orm.VerifierCreator;
2520

2621
import java.util.List;

0 commit comments

Comments
 (0)