|
14 | 14 | import java.sql.Savepoint; |
15 | 15 | import java.util.ArrayList; |
16 | 16 | import java.util.Arrays; |
| 17 | +import java.util.Comparator; |
17 | 18 | import java.util.HashMap; |
18 | 19 | import java.util.LinkedHashSet; |
19 | 20 | import java.util.List; |
20 | 21 | import java.util.Map; |
21 | 22 | import java.util.Map.Entry; |
22 | 23 | import java.util.Set; |
| 24 | +import java.util.SortedMap; |
| 25 | +import java.util.TreeMap; |
23 | 26 | import java.util.concurrent.TimeoutException; |
24 | 27 |
|
25 | 28 | import javax.activation.UnsupportedDataTypeException; |
@@ -472,7 +475,7 @@ public JSONObject parseCorrectRequest(RequestMethod method, String tag, int vers |
472 | 475 | JSONObject object = null; |
473 | 476 | String error = ""; |
474 | 477 | try { |
475 | | - object = getStructure("Request", JSONRequest.KEY_TAG, tag, version); |
| 478 | + object = getStructure("Request", method.name(), tag, version); |
476 | 479 | } catch (Exception e) { |
477 | 480 | error = e.getMessage(); |
478 | 481 | } |
@@ -665,34 +668,91 @@ public JSONObject parseCorrectResponse(String table, JSONObject response) throws |
665 | 668 |
|
666 | 669 | /**获取Request或Response内指定JSON结构 |
667 | 670 | * @param table |
668 | | - * @param key |
669 | | - * @param value |
| 671 | + * @param method |
| 672 | + * @param tag |
670 | 673 | * @param version |
671 | 674 | * @return |
672 | 675 | * @throws Exception |
673 | 676 | */ |
674 | 677 | @Override |
675 | | - public JSONObject getStructure(@NotNull String table, String key, String value, int version) throws Exception { |
676 | | - //获取指定的JSON结构 <<<<<<<<<<<<<< |
677 | | - SQLConfig config = createSQLConfig().setMethod(GET).setTable(table); |
678 | | - config.setPrepared(false); |
679 | | - config.setColumn(Arrays.asList("structure")); |
680 | | - |
681 | | - Map<String, Object> where = new HashMap<String, Object>(); |
682 | | - where.put("method", requestMethod.name()); |
683 | | - if (key != null) { |
684 | | - where.put(key, value); |
685 | | - } |
686 | | - if (version > 0) { |
687 | | - where.put(JSONRequest.KEY_VERSION + "{}", ">=" + version); |
688 | | - } |
689 | | - config.setWhere(where); |
690 | | - config.setOrder(JSONRequest.KEY_VERSION + (version > 0 ? "+" : "-")); |
691 | | - config.setCount(1); |
692 | | - |
693 | | - //too many connections error: 不try-catch,可以让客户端看到是服务器内部异常 |
694 | | - JSONObject result = getSQLExecutor().execute(config, false); |
695 | | - return getJSONObject(result, "structure");//解决返回值套了一层 "structure":{} |
| 678 | + public JSONObject getStructure(@NotNull String table, String method, String tag, int version) throws Exception { |
| 679 | + // TODO 目前只使用 Request 而不使用 Response,所以这里写死用 REQUEST_MAP,以后可能 Response 表也会与 Request 表合并,用字段来区分 |
| 680 | + String cacheKey = AbstractVerifier.getCacheKeyForRequest(method, tag); |
| 681 | + SortedMap<Integer, JSONObject> versionedMap = AbstractVerifier.REQUEST_MAP.get(cacheKey); |
| 682 | + |
| 683 | + JSONObject result = versionedMap == null ? null : versionedMap.get(Integer.valueOf(version)); |
| 684 | + if (result == null) { // version <= 0 时使用最新,version > 0 时使用 > version 的最接近版本(最小版本) |
| 685 | + Set<Entry<Integer, JSONObject>> set = versionedMap == null ? null : versionedMap.entrySet(); |
| 686 | + |
| 687 | + if (set != null && set.isEmpty() == false) { |
| 688 | + Entry<Integer, JSONObject> maxEntry = null; |
| 689 | + |
| 690 | + for (Entry<Integer, JSONObject> entry : set) { |
| 691 | + if (entry == null || entry.getKey() == null || entry.getValue() == null) { |
| 692 | + continue; |
| 693 | + } |
| 694 | + |
| 695 | + if (version <= 0 || version == entry.getKey()) { // 这里应该不会出现相等,因为上面 versionedMap.get(Integer.valueOf(version)) |
| 696 | + maxEntry = entry; |
| 697 | + break; |
| 698 | + } |
| 699 | + |
| 700 | + if (entry.getKey() < version) { |
| 701 | + break; |
| 702 | + } |
| 703 | + |
| 704 | + maxEntry = entry; |
| 705 | + } |
| 706 | + |
| 707 | + result = maxEntry == null ? null : maxEntry.getValue(); |
| 708 | + } |
| 709 | + |
| 710 | + if (result != null) { // 加快下次查询,查到值的话组合情况其实是有限的,不属于恶意请求 |
| 711 | + if (versionedMap == null) { |
| 712 | + versionedMap = new TreeMap<>(new Comparator<Integer>() { |
| 713 | + |
| 714 | + @Override |
| 715 | + public int compare(Integer o1, Integer o2) { |
| 716 | + return o2 == null ? -1 : o2.compareTo(o1); // 降序 |
| 717 | + } |
| 718 | + }); |
| 719 | + } |
| 720 | + |
| 721 | + versionedMap.put(Integer.valueOf(version), result); |
| 722 | + AbstractVerifier.REQUEST_MAP.put(cacheKey, versionedMap); |
| 723 | + } |
| 724 | + } |
| 725 | + |
| 726 | + if (result == null) { |
| 727 | + if (AbstractVerifier.REQUEST_MAP.isEmpty() == false) { |
| 728 | + return null; // 已使用 REQUEST_MAP 缓存全部,但没查到 |
| 729 | + } |
| 730 | + |
| 731 | + //获取指定的JSON结构 <<<<<<<<<<<<<< |
| 732 | + SQLConfig config = createSQLConfig().setMethod(GET).setTable(table); |
| 733 | + config.setPrepared(false); |
| 734 | + config.setColumn(Arrays.asList("structure")); |
| 735 | + |
| 736 | + Map<String, Object> where = new HashMap<String, Object>(); |
| 737 | + where.put("method", method); |
| 738 | + where.put(JSONRequest.KEY_TAG, tag); |
| 739 | + |
| 740 | + if (version > 0) { |
| 741 | + where.put(JSONRequest.KEY_VERSION + "{}", ">=" + version); |
| 742 | + } |
| 743 | + config.setWhere(where); |
| 744 | + config.setOrder(JSONRequest.KEY_VERSION + (version > 0 ? "+" : "-")); |
| 745 | + config.setCount(1); |
| 746 | + |
| 747 | + //too many connections error: 不try-catch,可以让客户端看到是服务器内部异常 |
| 748 | + result = getSQLExecutor().execute(config, false); |
| 749 | + |
| 750 | + // version, method, tag 组合情况太多了,JDK 里又没有 LRUCache,所以要么启动时一次性缓存全部后面只用缓存,要么每次都查数据库 |
| 751 | + // versionedMap.put(Integer.valueOf(version), result); |
| 752 | + // AbstractVerifier.REQUEST_MAP.put(cacheKey, versionedMap); |
| 753 | + } |
| 754 | + |
| 755 | + return getJSONObject(result, "structure"); //解决返回值套了一层 "structure":{} |
696 | 756 | } |
697 | 757 |
|
698 | 758 |
|
|
0 commit comments